如何使用const值优雅地赋予可选项

时间:2017-07-27 20:53:56

标签: c++ optional c++17

我正在尝试使用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中),因为它试图用Foo调用int const&, float const&的构造函数。 现在天真的我试图将emplace专门化为:

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

因为它尝试使用initializer_list而无效。

所以我的问题是如何优雅地召唤出来?

2 个答案:

答案 0 :(得分:6)

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

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

    int foo1;
    float foo2;
};

或明确使用的构造函数:

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

答案 1 :(得分:0)

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

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< aggregate_wrapper< Foo > >的方式。

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