使用boost :: optional时避免临时

时间:2014-08-07 14:54:12

标签: c++ boost optional

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);

谢谢!

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(最终......)

最终,我们将访问std::optional。此类型将实现emplace()方法,该方法也将实现就地构造。

#include <optional>

int main() {
    std::optional<int> x;
    x.emplace(3);
}

boost :: optional(很快......)

在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_placeboost::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();