I have the following problem. I have a singleton with a getInstance member function that returns an instance. I call this somewhere in code and for some reason VC tries to call the copy constructor. Why is this? How do I fix this?
The header:
class FileSystemEntryCollection {
public:
static FileSystemEntryCollection &getInstance();
private:
FileSystemEntryCollection();
FileSystemEntryCollection(FileSystemEntryCollection const&);
void operator=(FileSystemEntryCollection const&);
}
Source file:
FileSystemEntryCollection &FileSystemEntryCollection::getInstance() {
static FileSystemEntryCollection instance = FileSystemEntryCollection();
return instance;
}
The following line calls the copy constructor:
auto collection = FileSystemEntryCollection::getInstance();
I've tried to leave in the relevant code, let me know if something else is needed.
auto collection = FileSystemEntryCollection::getInstance();
needs to be:
auto& collection = FileSystemEntryCollection::getInstance();
^
auto on its own is never a reference type.
With a different compiler you'll get the same error for the initialization of instance.
static FileSystemEntryCollection instance = FileSystemEntryCollection();
The = here calls for copy construction: formally, the compiler creates a temporary (FileSystemEntryCollection()), and copies that into instance. However, in this situation, compilers are allowed to skip the copy construction and construct the object directly in place. That's what your compiler is doing. But compilers aren't required to do this.
Better:
static FileSystemEntryCollection instance;
which uses the default constructor to create instance.
It calls the copy constructor once inside the source file which constructs the static singleton object.
Related
I am trying to implement a singleton class that has to be used in two different threads, one sets up its member variables and the other one uses them, but the constructor is being called twice so I cannot use the members set in the first thread because they have their default value.
The implementation is quite standard, a static function that returns a reference to a static member in that function, I have tried to return a pointer, create a raw pointer and return it and the constructor always is called twice.
class Singleton
{
public:
static Singleton &getInstance()
{
static Singleton instance;
return instance;
}
// public methods
private:
Singleton();
Singleton(const Singleton &) = delete;
Singleton(Singleton &&) = delete;
Singleton &operator=(const Singleton &) = delete;
Singleton &operator=(Singleton &&) = delete;
// member variables
};
The thread trying to access to the singleton has been created using std::async(std::launch::async, lambda)
I expected that instance's constructor is called just the first time I call this function, but the second time instance has a different memory direction.
The C++11 standard guarantees that static local variables are only created once.
This leaves us with the following options:
Your compiler isn't C++11-compliant. Could be because it's old or
you're using the wrong options.
Your Singleton throws an (uncaught) exception, and the
initialization is attempted again.
Your constructor calls getInstance(), which results in undefined
behavior.
The above assumes you've implemented the Singleton pattern correctly. You could've also just messed up in some way, but I can't tell because you haven't provided the full code.
All the info taken from cppreference on static local variables.
In a class I have a static member that represents the singleton instance of that class:
class A {
public:
static const std::shared_ptr<A> INSTANCE;
private:
A();
};
In order to prevent more instances I made the constructor private. Now I have trouble to initialize the static var, because the initializer cannot access a private member. Here's the code I use in the .cpp file:
const std::shared_ptr<A> A::INSTANCE = std::make_shared<A>();
A factory method wouldn't help either, as it would have to be public as well. What else can I do to make this work? Note: I'd like to avoid the typical static get() method if possible.
You can't use make_shared, but you can just create the instance directly:
const std::shared_ptr<A> A::INSTANCE { new A };
The initialization of a static member is unrelated to the constructor, so the global statement is indeed the right way to go. Is it not working for you?
EDIT: I just realized you're trying to avoid using a singleton access method for some reason. Sounds suspiciously like the Borg pattern. :) Unrelated to you r specific question but I'd advise you to reconsider.
I am using a library with a class that does not have an assignment operator implemented and the copy constructor is disabled. I can instantiate a local instance of LibraryClass named var like this:
LibraryClass var(data, (char *)fileName, results);
But I want to create a LibraryClass instance variable on the class I am writing. Then I want to instantiate it in the class constructor. Something like this:
class MyClass
{
LibraryClass var;
void MyClass();
}
MyClass::MyClass()
{
var = LibraryClass(data, (char *)fileName, results);
}
In this case I end up with
error: ‘LibraryClass& LibraryClass::operator=(const LibraryClass&)’ is private
LibraryClass& operator=(const LibraryClass& rOther); // no implementation
I have tried everything I can imagine to make this work but nothing is working. Is what I am attempting to do even possible? I am out of ideas so any suggestion is much appreciated.
EDIT
I'm not actually instantiating the variable in the constructor. It's happening in a separate function. I only said constructor because I mistakenly thought it was just a simplifying assumption. I didn't realize that the initialization list would solve that problem. The main question I want to answer is the title.
How can I instantiate an instance variable of a class that doesn't have a copy constructor or assignment operator? Or is the initialization list the only way to do it?
You need to use the initialization list.
Constructors and member initializer lists
MyClass::MyClass() :
var(data, (char*) fileName, results))
{
}
I'm experiencing a weird issue in which I need to have a default constructor for my template class to work, but some of the classes I'd like to use with the template cannot have default constructors.
What I mean by some classes cannot have default constructors is they have a const reference field, hence, they must be set in the constructor/initialization list. If I have a default constructor, there is nothing to set these references to.
So, I guess there are two possible solutions to this: Find a way to allow for non-default constructors in the template class sometimes or find a way to set the const reference fields in a default constructor.
How do I resolve this?
Here's my template code:
#pragma once
template<class T>
class Singleton
{
public:
static T* getInstance()
{
if(!instance) instance = new T;
return instance;
}
static void setInstance(T* inst)
{
instance = inst;
}
protected:
Singleton();
~Singleton();
private:
Singleton(Singleton const&);
Singleton& operator=(Singleton const&);
static T* instance;
};
template<class T> T* Singleton<T>::instance = 0;
Here's where I set the const reference (in a .cpp):
InputHandler::InputHandler(const sf::Input& inputObject)
: input(inputObject)
{
And input is defined in the header:
const sf::Input& input;
I have to use a constant reference because of this area of code (in a different file):
const sf::Input& input = window.GetInput();
InputHandler* inputHandler = new InputHandler(input);
Singleton<InputHandler>::setInstance(inputHandler);
GetInput() is not one of my methods, and it must return a const sf::Input&
You're invoking the default constructor in getInstance with:
instance = new T;
What do you expect to happen if someone calls getInstance before setInstance?
If it's an error to call getInstance before setInstance, then getInstance should assert or throw or return NULL if called before instance is set. Just get rid of the new T, and your code will compile.
If it's not an error to call getInstance before setInstance, then you don't really have a singleton. Early callers would receive a default constructed object and later callers would get the one set later. That's two instances and therefore not a singleton.
If you have a reference member, then you cannot (sensibly) make your class default-constructible or assignable, since references must be initialised, and can't be reassigned.
If you need those properties from the class, then you probably want the member to be a pointer, initialised to null by default and assignable later if needed.
You could perhaps have the Singleton constructor set the instance pointer, i.e.
Singleton::Singleton()
{
assert(instance == nullptr);
instance = static_cast<T*>(this);
}
You can then remove the setInstance function from the interface and getInstance can simply return instance.
In response to the comment, I was assuming that classes were being defined like this:
class MyClassThatShouldBeASingleton : public Singleton<MyClassThatShouldBeASingleton>
{
};
Of course, this does mean that you need to explicitly set up such a singleton rather than it instantiating automatically as in the original code. It's not necessarily how you'd want all singletons to work, just one way of solving the problem.
EDIT: See GWW's answer, the problem was simply making an illicit copy with C::Instance(). And I was wrong, the error does not depend on mutable.
Are static methods incompatible with mutable methods? Here's a simplified version of my code:
c.h:
class C
{
public:
static C& Instance();
private:
C();
mutable QMutex _mutex;
};
c.cpp:
C& C::Instance()
{
static C instance;
return instance;
}
C c = C::Instance();
Then the error I'm getting (gcc 4.2) is
error: 'QMutex::QMutex(const QMutex&)' is private within this context
synthesized method 'C::C(const C&)' first required here //at C::Instance()
If I remove the 'mutable' keyword this error goes away, but then of course I can't make the methods that lock/unlock _mutex const. Writing my own copy ctor doesn't change anything. Anyone know how to solve this? NB this looks similar to this post but that's objective-C and there was just too much code in there that didn't seem relevant to the question.
EDIT: Just realized that the problem, obviously, is that QMutex's copy ctor is private. But I don't understand why 'mutable' should make a difference here, i.e. why it induces a copy.
You are trying to copy your singleton and it fails because you have declared a copy constructor private. It has absolutely nothing to do with mutable members.