【问题标题】:How to rewrite with boost::optional in C++11?如何在 C++11 中用 boost::optional 重写?
【发布时间】:2021-01-22 06:32:29
【问题描述】:

如何在 C++11 中重写以下代码以使用 boost::optionalboost::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;                                        

}

【问题讨论】:

  • 我不确定是否将智能指针包装到optional 中。 std::unique_ptr 已经有一个null-state,所以你基本上会加倍。想象一下:if (foo &amp;&amp; *foo) 是必需的,以确保可选项有一个值并且包装的智能指针是活动的......
  • make_unique 不是 c++11 顺便说一句
  • 也许这answer 有帮助
  • 您也可以考虑完全不使用 std::function,切换到 unordered_map 并且如果您能够使用 c++17 切换到 string_view :godbolt.org/z/xEvG5P 比较所有 3 个版本的 disassmbly自己看看
  • @Yamahari 在 C++17 之前你已经可以使用 boost::string_refboost::string_view

标签: c++ c++11 boost-optional stdoptional


【解决方案1】:

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

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

不过,您可以使用另一种被 C++17 标准采用的 Boost 类型:boost::variant。这是一个类型安全的tagged union,可以在同一内存空间中保存一组类型中的一个。只需添加一个表示“none”的类型(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

【讨论】:

    猜你喜欢
    • 2012-08-06
    • 1970-01-01
    • 2014-04-09
    • 2019-12-27
    • 2014-11-21
    • 2011-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多