【问题标题】:How to elegantly emplace optional with const values如何优雅地使用 const 值替换可选项
【发布时间】:2017-07-29 13:18:34
【问题描述】:

我正在尝试使用std::optional 来延迟实例化对象(之前无效)。我发现了一个烦人的情况,我不知道如何优雅地解决这个问题。

我有以下数据结构:

struct Foo {
    int foo1;
    float foo2;
};

作为会员std::optional<Foo> foo_

在函数中

void Bar::bar(int const value1, float const value2) {
    foo_.emplace(value1, value2);
}

令我惊讶的是,它无法编译(在 GCC 7.1 中),因为它试图用 int const&, float const& 调用 Foo 的构造函数。 现在天真的我试图将emplace 专业化为:

foo_.emplace<int, float>(value1, value2);

这也不起作用,因为它尝试使用initializer_list

所以我的问题是如何优雅地调用 emplace?

【问题讨论】:

  • 提示:你将如何构造一个 Foo 开始?

标签: c++ optional c++17


【解决方案1】:

您必须将构造函数添加为 emplace 使用 () 构造函数而不是 {}(这将允许聚合初始化)。

struct Foo {
     Foo(int i, float f) : foo1(i), foo2(f) {}

    int foo1;
    float foo2;
};

或明确使用的构造函数:

foo_.emplace(Foo{value1, value2});

【讨论】:

  • “明确使用构造函数”有点误导,因为您的示例代码将隐式使用移动构造函数;)
【解决方案2】:

您可以使用以下包装器来包装聚合:

template< typename type >
struct aggregate_wrapper
    : type
{

    aggregate_wrapper() = default;

    using type::operator =;

    template< typename ...arguments,
              bool is_noexcept = noexcept(::new (std::declval< void * >()) type{std::declval< arguments >()...}) >
    constexpr
    aggregate_wrapper(arguments &&... _arguments) noexcept(is_noexcept)
        : type{std::forward< arguments >(_arguments)...}
    { ; }

};

std::optional&lt; aggregate_wrapper&lt; Foo &gt; &gt;的方式。

对于像std::vector 这样的分配器感知容器,您可以使用here 中提到的分配器的修改(即在construct 内使用花括号而不是括号)。

【讨论】:

    猜你喜欢
    • 2010-11-19
    • 1970-01-01
    • 2019-04-12
    • 1970-01-01
    • 2011-05-25
    • 2021-12-27
    • 1970-01-01
    • 2021-12-26
    • 2019-11-12
    相关资源
    最近更新 更多