return 不允许隐式转换
Implicit conversion not allowed on return
#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
不编译:'return': cannot convert from 'std::optional<int>' to 'bool'
咨询参考本来想找个解释,结果看了下应该没问题
Implicit conversions are performed whenever an expression of some type
T1 is used in context that does not accept that type, but accepts some
other type T2; in particular:
- when the expression is used as the argument when calling a function that is declared with T2 as parameter;
- when the expression is used as an operand with an operator that expects T2;
- when initializing a new object of type T2, including return statement in a function returning T2;
- when the expression is used in a switch statement (T2 is integral type);
- when the expression is used in an if statement or a loop (T2 is bool).
std::optional
没有任何隐式转换为 bool
的工具。 (允许隐式转换为 bool
通常被认为是一个坏主意,因为 bool
是一个整数类型,所以像 int i = opt
这样的东西会编译并做完全错误的事情。)
std::optional
是否有一个 "contextual conversion" 布尔值,其定义看起来类似于强制转换运算符:explicit operator bool()
。这不能用于隐式转换;它仅适用于某些特定情况,其中预期的 "context" 是布尔值,例如 if 语句的条件。
你要的是opt.has_value()
.
来自 C++ docs:
When an object of type optional< T > is contextually converted to bool,
the conversion returns true if the object contains a value and false
if it does not contain a value.
了解上下文转换here:
In the following contexts, the type bool is expected and the implicit
conversion is performed if the declaration bool t(e); is well-formed
(that is, an explicit conversion function such as explicit T::operator
bool() const; is considered). Such expression e is said to be
contextually converted to bool.
- the controlling expression of if, while, for;
- the operands of the built-in logical operators !, && and ||;
- the first operand of the conditional operator ?:;
- the predicate in a static_assert declaration;
- the expression in a noexcept specifier;
- the expression in an explicit specifier;
您可以进行以下破解:
bool f() {
std::optional<int> opt;
return opt || false;
}
因为上下文转换发生在内置逻辑运算符的情况下,但上下文转换 不 包含 return
语句并且 std::optional
本身包含not 隐式转换为 bool
。
因此,最好使用 std::optional<T>::has_value
:
bool f() {
std::optional<int> opt;
return opt.has_value();
}
那是因为不支持将 std::optional 隐式转换为布尔值:https://en.cppreference.com/w/cpp/utility/optional/operator_bool
constexpr explicit operator bool() const noexcept;
您必须显式转换为布尔值 bool(opt)
或简单地使用 opt.has_value()
代替。
这与隐式转换无关,与初始化类型有关。
可选的是显式转换函数,即
explicit operator bool() const;
来自 N4849 [class.conv.fct]/p2
A conversion function may be explicit (9.2.2), in which case it is only considered as a user-defined conversion
for direct-initialization.
上面的意思就是这些情况会用到转换函数:
[dcl.init]/p16
The initialization that occurs
(16.1) — for an initializer that is a parenthesized expression-list or a braced-init-list,
(16.2) — for a new-initializer (7.6.2.7),
(16.3) — in a static_cast expression (7.6.1.8),
(16.4) — in a functional notation type conversion (7.6.1.3), and
(16.5) — in the braced-init-list form of a condition is called direct-initialization.
但是,这些情况不会使用转换功能:
[dcl.init]/p15
The initialization that occurs in the = form of a
brace-or-equal-initializer or condition (8.5), as well as in argument
passing, function return, throwing an exception (14.2), handling an
exception (14.4), and member initialization (9.4.1), is called
copy-initialization.
题中的例子属于复制初始化的情况,没有使用optional的转换函数
#include <optional>
bool f() {
std::optional<int> opt;
return opt;
}
不编译:'return': cannot convert from 'std::optional<int>' to 'bool'
咨询参考本来想找个解释,结果看了下应该没问题
Implicit conversions are performed whenever an expression of some type T1 is used in context that does not accept that type, but accepts some other type T2; in particular:
- when the expression is used as the argument when calling a function that is declared with T2 as parameter;
- when the expression is used as an operand with an operator that expects T2;
- when initializing a new object of type T2, including return statement in a function returning T2;
- when the expression is used in a switch statement (T2 is integral type);
- when the expression is used in an if statement or a loop (T2 is bool).
std::optional
没有任何隐式转换为 bool
的工具。 (允许隐式转换为 bool
通常被认为是一个坏主意,因为 bool
是一个整数类型,所以像 int i = opt
这样的东西会编译并做完全错误的事情。)
std::optional
是否有一个 "contextual conversion" 布尔值,其定义看起来类似于强制转换运算符:explicit operator bool()
。这不能用于隐式转换;它仅适用于某些特定情况,其中预期的 "context" 是布尔值,例如 if 语句的条件。
你要的是opt.has_value()
.
来自 C++ docs:
When an object of type optional< T > is contextually converted to bool, the conversion returns true if the object contains a value and false if it does not contain a value.
了解上下文转换here:
In the following contexts, the type bool is expected and the implicit conversion is performed if the declaration bool t(e); is well-formed (that is, an explicit conversion function such as explicit T::operator bool() const; is considered). Such expression e is said to be contextually converted to bool.
- the controlling expression of if, while, for;
- the operands of the built-in logical operators !, && and ||;
- the first operand of the conditional operator ?:;
- the predicate in a static_assert declaration;
- the expression in a noexcept specifier;
- the expression in an explicit specifier;
您可以进行以下破解:
bool f() {
std::optional<int> opt;
return opt || false;
}
因为上下文转换发生在内置逻辑运算符的情况下,但上下文转换 不 包含 return
语句并且 std::optional
本身包含not 隐式转换为 bool
。
因此,最好使用 std::optional<T>::has_value
:
bool f() {
std::optional<int> opt;
return opt.has_value();
}
那是因为不支持将 std::optional 隐式转换为布尔值:https://en.cppreference.com/w/cpp/utility/optional/operator_bool
constexpr explicit operator bool() const noexcept;
您必须显式转换为布尔值 bool(opt)
或简单地使用 opt.has_value()
代替。
这与隐式转换无关,与初始化类型有关。
可选的是显式转换函数,即
explicit operator bool() const;
来自 N4849 [class.conv.fct]/p2
A conversion function may be explicit (9.2.2), in which case it is only considered as a user-defined conversion for direct-initialization.
上面的意思就是这些情况会用到转换函数: [dcl.init]/p16
The initialization that occurs (16.1) — for an initializer that is a parenthesized expression-list or a braced-init-list, (16.2) — for a new-initializer (7.6.2.7), (16.3) — in a static_cast expression (7.6.1.8), (16.4) — in a functional notation type conversion (7.6.1.3), and (16.5) — in the braced-init-list form of a condition is called direct-initialization.
但是,这些情况不会使用转换功能: [dcl.init]/p15
The initialization that occurs in the = form of a brace-or-equal-initializer or condition (8.5), as well as in argument passing, function return, throwing an exception (14.2), handling an exception (14.4), and member initialization (9.4.1), is called copy-initialization.
题中的例子属于复制初始化的情况,没有使用optional的转换函数