首页 > 解决方案 > 如何在 C++11 中用 boost::optional 重写?

问题描述

如何在 C++11 中重写以下代码以使用boost::optionalor ?boost::none

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;                                        

}

标签: c++c++11boost-optionalstdoptional

解决方案


那么,您希望它返回值类型而不是指针吗?

由于object slicingboost::optional ,这在(或在 c++17 中)是不可能的。对于值类型,您只能返回包含的信息,因此当您从其中一种派生类型向上转换时,您将丢失信息。std::optionalFooBase

不过,为此,您可以使用另一种被 C++17 标准采用的 Boost 类型:boost::variant. 这是一个类型安全的标记联合,可以在同一内存空间中保存一组类型中的一个。只需添加一个类型来表示“无”(std::monostate' 在 C++17 中boost::blank的用途和 ' 在 Boost 中的用途),然后添加每个派生类型:

struct Bar1 { };
struct Bar2 { };
using Bar = boost::variant<boost::blank, Bar1, Bar2>;

然后你可以像这样重写你的函数:

Bar find( std::string key)
{
    std::map<std::string, std::function<Bar()> > m {
        {"key1", [](){return Bar1 {}; } },
        {"key2", [](){return Bar2 {}; } } 
    };
                                        
    auto it = m.find(key);
    if (it != std::end(m))
        return (it->second());  
    else 
        return { }; // default-constructs the first variant, in this case blank
}

https://godbolt.org/z/dcYevv


推荐阅读