Reputation: 365
I have build a factory pattern using new C++11 features. To achieve this a std::function is registered in the registry. Now I am trying to implement the instantiation part. Right now it is implemented like this:
std::map<uint32_t, std::function<Class*()>>::iterator it = m_creators.find(id);
if(it != m_creators.end())
{
return std::shared_ptr<Class>((it->second)());
}
The problem is, that is is obviously not exception save and I am trying to replace the std::shared_ptr call with a equivalent std::make_shared call. The std::function is a create function that only calls the constructor of a Object subclass. The problem is that I have no idea how to use the std::function instead of the call to the constructor in std::make shared. Is this even possible?
Upvotes: 1
Views: 1690
Reputation: 109149
The code you have is not exception unsafe. The shared_ptr
constructor that takes a pointer will call delete
on the managed pointer if an exception occurs during initialization.
From N3797, §20.8.2.2.1/7
template<class Y> explicit shared_ptr(Y* p);
...
Exception safety: If an exception is thrown,delete p
is called.
If it makes you feel better, you could change the map
type to
std::map<uint32_t, std::function<std::unique_ptr<Class>()>>
shared_ptr
s can be constructed from unique_ptr
s, and you're never passing around a raw pointer in this case. But it is unnecessary because of the clause I quoted above.
Upvotes: 1
Reputation: 5552
I would make the std::function return a shared_ptr rather than a naked pointer. Then you could use make_shared inside the std::function.
typedef std::map<uint32_t, std::function<std::shared_ptr<Class>()>> CreatorMap;
CreatorMap::iterator it = m_creators.find(id);
if(it != m_creators.end())
{
return (it->second)();
}
// example of a creator
struct SomeCreator{
public:
std::shared_ptr<Class> operator()(){
return std::make_shared<Class>();
}
}
this also allows more flexibility to allow the factory to use custom deleter.
Upvotes: 2