How do I rewrite the following code to use boost::optional
or boost::none
, in C++11?
std::unique_ptr<FooBase> find( std::string key)
{
std::map<std::string, std::function<std::unique_ptr<FooBase>(void)> > m{
{"key1", [](){return std::make_unique<BarDerived>();} },
{"key2", [](){return std::make_unique<BarDerived1>();} } };
auto it = m.find(key);
if (it != std::end(m))
return (it->second());
else
return nullptr;
}
So, you want this to return a value type instead of a pointer?
That isn't possible with
boost::optional
(orstd::optional
in c++17), because of object slicing. For a value type, you can only return as much information asFooBase
contains, so you'll lose information when you upcast from one of the derived types.For this though, you can use another Boost type that got adopted by the C++17 standard:
boost::variant
. This is a type-safe tagged union that can hold one of a set of types in the same memory space. Just add a type to represent "none" (std::monostate
's purpose in C++17, andboost::blank
's purpose in Boost), and then add each derived type:Then you can rewrite your function like this:
https://godbolt.org/z/dcYevv