boost ::可选支持in_place构造,如下所示:
#include <boost/optional.hpp>
#include <boost/utility/typed_in_place_factory.hpp>
class Foo
{
int a,b;
public:
Foo(int one, int two) : a(one),b(two) {}
};
int main()
{
boost::optional<Foo> fooOpt(boost::in_place<Foo>(1,3));
}
一旦我们有了一个初始化的fooOpt,有没有一种方法可以为它分配一个新的Foo而不创建一个临时的?
类似的东西:
fooOpt = boost::in_place<Foo>(1,3);
谢谢!
答案 0 :(得分:9)
#include <boost/optional.hpp>
int main() {
boost::optional<int> x;
x = boost::in_place(3);
}
我们还可以显示(通过代码)这是通过Foo
继承boost::noncopyable
来就地构建对象:
#include <boost/optional.hpp>
#include <boost/noncopyable.hpp>
class Foo : boost::noncopyable {
public:
Foo(int one, int two) {}
};
int main() {
boost::optional<Foo> x;
x = boost::in_place(3, 4);
}
最终,我们将访问std::optional
。此类型将实现emplace()
方法,该方法也将实现就地构造。
#include <optional>
int main() {
std::optional<int> x;
x.emplace(3);
}
在1.56.0版中,boost::optional
还将实现我为std :: optional所讨论的emplace()
方法。所以,让我们看看:
#include <boost/optional.hpp>
int main() {
boost::optional<int> x;
x.emplace(3);
}
答案 1 :(得分:3)
文档化的界面不支持此功能。
但是,如果您知道没有人延伸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
构造应该在构造安全期间使大多数throw
:如果它抛出,你最终会得到一个空的optional
。
这自然与operator=
预期的行为不同。
在1.55(可能更早?)中,有一个未记录的operator=
,其Expr
支持boost::in_place
和boost::in_place<T>
。有关详细用途,请参阅@ sharth的答案。
我的快速阅读表明,通过此方法的类型就地工厂可能没有足够的警卫:
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
。
这(从阅读源代码)执行与我的destroy / reconstruct代码类似的操作,除了它在不破坏整个optional
的情况下执行它,并且只是破坏存储的数据并使其未初始化。
在提升1.56b1中,emplace已添加到boost::optional
。它执行类似于上述两个操作的操作。 (来自@AkiraTakahashi)
std::optional
个提案已经包含了一个支持直接替换的成员函数.emplace( Us&&... )
。
答案 2 :(得分:0)
一旦你知道它就在那里,你可以创建一个普通的引用:
optional<Foo> optFoo = ....;
Foo &foo = *optFoo;
foo.x = 3;
foofun(foo);
foo = Foo();