考虑以下示例,我们解析数据并将结果传递给下一个函数:
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
也有效吗?
答案 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));
}