文档化的接口不支持这个。
但是,如果您知道没有人扩展 boost::optional,我相信这在技术上可能是有效的:
template<typename T, typename... Us>
void emplace_replace( boost::optional<T>& target, Us&&... us ) {
target.~boost::optional<T>();
try {
new (&target) boost::optional<T>( boost::in_place( std::forward<Us>(us)...) );
} catch(...) {
new (&target) boost::optional<T>();
throw;
}
}
在这里,我们销毁target,然后通过就地构造重建一个新的boost::optional<T>。 try-catch 构造应该使大多数throws 在构造过程中安全:如果它抛出,你最终会得到一个空的optional。
这自然与operator= 预期的行为不同。
在 1.55(可能更早?)中,有一个未记录的 operator= 采用支持 boost::in_place 和 boost::in_place<T> 的 Expr。详细使用请参见@sharth 的回答。
我的快速阅读表明通过这种方法的 typed 就地工厂可能没有足够的防护:
boost::optional<int> test;
// test = boost::in_place<double>( 3 ); // <-- very dangerous
test = boost::in_place( 3 ); // safe
test = boost::in_place( 3.0 ); // safe
如果一个类型直接传递给in_place<?>,它会生成一个typed_in_place_factory,这是很危险的(他们制作传入的类型,并且不检查它是否兼容)。所以不要将任何类型传递给boost::in_place。
这(通过阅读源代码)执行类似于我的销毁/重建代码的操作,但它不会破坏整个 optional,只是破坏存储的数据并使其未初始化。
在 boost 1.56b1 中,emplace 已添加到 boost::optional。它执行与上述两种操作类似的操作。 (来自@AkiraTakahashi)
我看到的std::optional提案中包含了一个成员函数.emplace( Us&&... ),它支持直接替换emplace。