如何从std :: optional <t> </t>移动

时间:2013-07-06 11:37:40

标签: c++ std c++14 boost-optional

考虑以下示例,我们解析数据并将结果传递给下一个函数:

Content Parse(const std::string& data);
void Process(Content content);

int main()
{
    auto data = ReadData();
    Process(Parse(data));    
}

现在让我们使用std::optional更改代码以处理失败的解析步骤:

optional<Content> Parse(const std::string& data);
void Process(Content content);

int main()
{
    auto data = ReadData();
    auto content = Parse(data);
    if (content)
        Process(move(*content));
}

optional<T>::value()移出是否有效?如果std::optional可以,它对boost::optional也有效吗?

2 个答案:

答案 0 :(得分:12)

optional<T>::value()移动是有效的,因为它返回一个可变引用,并且移动不会破坏该对象。如果optional实例未参与,则value()将引发bad_optional_access例外(第20.6.4.5节)。

您明确检查该选项是否参与:

if (content)
    Process(move(*content));

但您不使用成员value()来访问基础T。请注意,value()在返回有效T&之前会在内部执行检查,而operator*具有optional实例应具有的前提条件。这是一个微妙的区别,但你使用正确的习语:

if (o)
  f(*o)

而不是

if (o)  // redundant check
  f(o.value())

在Boost中,情况略有不同:首先,没有名为value()的成员函数提供检查访问。 (根本不存在bad_optional_access例外)。成员get()只是operator*的别名,并且始终依赖于用户检查optional实例的参与情况。

答案 1 :(得分:-1)

对于您当前的实现,答案是否定的。但是,如果您稍作更改,则可以移动值。可选的运算符*(以及方法 value())有4个重载。并且只有其中两个将右值引用( _Ty && const _Ty && )返回给封装的值。但是它们分别具有签名 && const && 。这意味着只有当右值引用访问了可选变量本身时,才可以使用它们。在这种情况下,实现应如下所示:

std::optional<Content> Parse(const std::string& data);
void Process(Content content);

int main()
{
    auto data = ReadData();
    auto content = Parse(data);
    if (content)
        Process(*std::move(content));
}