I have a singleton class declaration here:
#ifndef GLFW_CONTEXT_H
#define GLFW_CONTEXT_H
#include <memory>
class GLFWContextSingleton
{
public:
static std::shared_ptr<GLFWContextSingleton> GetInstance();
~GLFWContextSingleton();
GLFWContextSingleton(const GLFWContextSingleton& other) = delete;
GLFWContextSingleton* operator=(const GLFWContextSingleton* other) = delete;
private:
GLFWContextSingleton();
};
#endif
and an implementation of the GetInstance
function shown here
std::shared_ptr<GLFWContextSingleton> GLFWContextSingleton::GetInstance()
{
static std::weak_ptr<GLFWContextSingleton> weak_singleton_instance;
auto singleton_instance = weak_singleton_instance.lock();
if (singleton_instance == nullptr)
{
singleton_instance = std::make_shared<GLFWContextSingleton>();
weak_singleton_instance = singleton_instance;
}
return singleton_instance;
}
However the call to std::make_shared<GLFWContextSingleton>()
gives me an error saying
‘GLFWContextSingleton::GLFWContextSingleton()’ is private within this context
I thought that this static method would have access to the private member functions. What is causing this and how do I fix it?
CodePudding user response:
The static function does have access to private members. make_shared
does not.
make_shared
is a template function that forwards the arguments it gets and calls the constructor of the specified class. So the call to the default constructor happens inside the make_shared
function, not inside the GetInstance
function, hence the error.
One way to deal with this is to use a private nested class as the only argument to the constructor.
#include <memory>
class GLFWContextSingleton
{
private:
struct PrivateTag {};
public:
static std::shared_ptr<GLFWContextSingleton> GetInstance();
~GLFWContextSingleton();
GLFWContextSingleton(const GLFWContextSingleton& other) = delete;
GLFWContextSingleton* operator=(const GLFWContextSingleton* other) = delete;
GLFWContextSingleton(PrivateTag);
};
std::shared_ptr<GLFWContextSingleton> GLFWContextSingleton::GetInstance()
{
static std::weak_ptr<GLFWContextSingleton> weak_singleton_instance;
auto singleton_instance = weak_singleton_instance.lock();
if (singleton_instance == nullptr)
{
singleton_instance = std::make_shared<GLFWContextSingleton>(PrivateTag{});
weak_singleton_instance = singleton_instance;
}
return singleton_instance;
}
int main() {
}
This way we keep the constructor public, but in order to use it we need a PrivateTag
, only accessible to members of the class.