我正在尝试使用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
而无效。
所以我的问题是如何优雅地召唤出来?
答案 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
内的花括号而不是括号)。