我们什么时候可以使用统一初始化来轻松地默认构造std::optional<T>
?
std::optional<T> foo() {
if (on_error)
return {};
// ...
}
std::nullopt
解决了上述情况存在的任何缺陷吗?
编号。
这是一种完全有效的默认构造optional
的方式。
即使是赋值,您也可以使用= {}
而不是使用std::nullopt
来复制赋值一个默认构造的optional
:
cppreference实际上已经说明了这一点:
nullopt_t
的构造函数的约束存在是为了支持将可选对象解除关联的语法,包括op = {};
和op = nullopt;
。
… 原始的特性提案也说明了这一点:
请注意,这不是将可选对象解除关联的唯一方法。 您还可以使用:
你可能会问为什么需要存在
op = std::nullopt;
std::nullopt
。提案也解释了这个问题:它在接口中引入了冗余
[类似的例子]
另一方面,有些场景下,无法用其他便捷的符号替换 nullopt 的使用:
void run(complex<double> v); void run(optional<string> v); run(nullopt); // pick the second overload run({}); // ambiguous if (opt1 == nullopt) ... // fine if (opt2 == {}) ... // illegal bool is_engaged( optional<int> o) { return bool(o); // ok, but unclear return o != nullopt; // familiar }
虽然某些情况下使用{}语法是可以的,但使用nullopt会使程序员的意图更加清晰。请比较以下两种写法:
简而言之,
optional<vector<int>> get1() { return {}; } optional<vector<int>> get2() { return nullopt; } optional<vector<int>> get3() { return optional<vector<int>>{}; }
std::nullopt
可能很有用,但在你的情况下,它只是风格问题。
{}
初始化语法不能非歧义地用于推断std::nullopt_t
类型。例如,在通过三元运算符表达式返回空或非空可选值时,如Return Optional value with ?: operator所述。
return it != map.end() ? std::make_optional(it->second) : std::nullopt;
auto
的情况,对吗? - Sebastian Hoffmanntrue
表达式与返回类型匹配,但是,在那里 {}
不是一个有效的表达式。 (链接:https://coliru.stacked-crooked.com/a/222ee7027638ba2c) - Asteroids With Wings