Monday, February 6, 2012

C++11 factory

Today I was playing with awesome new features of C++11. In the examples below B is base class and D is derived.
The following code works fine:
std::function<std::shared_ptr<B>()> factory;
factory = [](){return std::make_shared<D>();};

The following code doesn't work:
auto factory = std::make_shared<B>;
factory = std::make_shared<D>;

The first code works because polymorphic wrappers for function objects are smart; the second does not work because function pointers are not smart at all. You can not cast from function that returns derived shared pointer to function that returns base shared pointer, you need function wrappers for it.
I tried to implement parametrized factory method. VC10 does not support initializer so the following did not work yet:
std::map<std::string, std::function<std::shared_ptr<B>()>> factory { 
    std::make_pair("D", [](){return std::make_shared<D>();}),
    std::make_pair("D1", [](){return std::make_shared<D1>();})
};

I'll test this trick with gcc4.6 tomorrow. In VC10 you can initialize the map by hand:
std::map<std::string, std::function<std::shared_ptr<B>()>> factory;
factory.emplace(std::make_pair("D", [](){return std::make_shared<D>();}));
factory.emplace(std::make_pair("D1", [](){return std::make_shared<D1>();}));

Please note the use of emplace method.
You can use factory like this:
auto Bptr = factory["D"]();
//Do something with D object...
Bptr = factory["D1"]();

Unfortunately std::make_unique is not a part of new standard, you can copy the code for make_unique from Sutter's blog. Factories returning unique_ptr are considered better.

1 comment:

lost_dm said...

Neat post!
Do go on posting nice findings ^_^