How to use make_shared for making the instance of singleton class. Instantiating singleton class gives error.
Mar 14, 2017 at 6:17pm Mar 14, 2017 at 6:17pm UTC
Hi ppl :),
I am trying to make instance of singleton class using make_shared. Getting error while instantiating the singleton class.
Kindly note that if we change the instance pointer from shared_ptr to raw pointer, animalFactory = new AnimalFactory(), program works well.
I am trying using the below code, but getting the following error :
animal_factory.cpp:22:61: required from here
/usr/include/c++/6/ext/new_allocator.h:120:4: error: ‘AnimalFactory::AnimalFactory()’ is private within this context
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
animal_factory.cpp:3:1: note: declared private here
AnimalFactory::AnimalFactory()
animal_factory.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#ifndef ANIMAL_FACTORY_H_
#define ANIMAL_FACTORY_H_
#include "animal_prototype.h"
#include "cat_prototype.h"
#include "snail_prototype.h"
#include <map>
#include <string>
#include <memory>
#include <mutex>
class AnimalFactory
{
private :
AnimalFactory();
AnimalFactory(const AnimalFactory &);
AnimalFactory& operator =(const AnimalFactory&);
static std::shared_ptr<AnimalFactory> animalFactory;
typedef std::map<std::string, std::unique_ptr<AnimalPrototype> > AnimalFactoryMap;
AnimalFactoryMap myMap;
static std::recursive_mutex mtx;
public :
virtual ~AnimalFactory();
static std::shared_ptr<AnimalFactory> getAnimalFactory();
std::unique_ptr<AnimalPrototype> getAnimal(const std::string &);
};
#endif
animal_factory.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#include "animal_factory.h"
AnimalFactory::AnimalFactory()
{
myMap["cat" ] = std::make_unique<CatPrototype>();
myMap["snail" ] = std::make_unique<SnailPrototype>();
}
AnimalFactory::AnimalFactory(const AnimalFactory &) {}
AnimalFactory::~AnimalFactory() {}
AnimalFactory& AnimalFactory::operator =(const AnimalFactory &other) { return *this ;}
std::shared_ptr<AnimalFactory> AnimalFactory::animalFactory;
std::recursive_mutex AnimalFactory::mtx;
std::shared_ptr<AnimalFactory> AnimalFactory::getAnimalFactory()
{
if (animalFactory == nullptr )
{
mtx.lock();
if (animalFactory == nullptr )
animalFactory = std::make_shared<AnimalFactory>(); //getting error
mtx.unlock(); //in this line
}
return animalFactory;
}
std::unique_ptr<AnimalPrototype> AnimalFactory::getAnimal(const std::string &animalType)
{
return myMap[animalType]->clone();
}
Thanks :)
Last edited on Mar 14, 2017 at 6:23pm Mar 14, 2017 at 6:23pm UTC
Mar 14, 2017 at 6:52pm Mar 14, 2017 at 6:52pm UTC
As the compiler said, your call to std::make_shared requires a default-constructible type, and yours isn't: its constructor is private.
You can get around this by using a private key idiom:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
class AnimalFactory
{
private :
+ struct token{};
AnimalFactory();
AnimalFactory(const AnimalFactory &);
...
public :
+ AnimalFactory(token) : AnimalFactory() {}
virtual ~AnimalFactory();
static std::shared_ptr<AnimalFactory> getAnimalFactory();
...
- animalFactory = std::make_shared<AnimalFactory>();
+ animalFactory = std::make_shared<AnimalFactory>(token{});
Also, why so many layers of complexity? Singletons are the thing to avoid, not to make (and so are the recursive mutexes, by the way), but if you must make a singleton, the standard C++ solution is just a reference to a function-local static:
1 2 3 4 5
AnimalFactory& AnimalFactory::getAnimalFactory()
{
static AnimalFactory instance;
return instance;
}
In the code shown, though, there's no need for even that. You can have a factory function without any class.
Last edited on Mar 14, 2017 at 7:18pm Mar 14, 2017 at 7:18pm UTC
Topic archived. No new replies allowed.