提问人:darune 提问时间:2/14/2020 最后编辑:darune 更新时间:4/12/2020 访问量:3794
返回时不允许隐式转换
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'
咨询参考资料 我本来想找到一个解释,但我读了它,因为它应该没问题。
每当某种类型的表达式出现时,都会执行隐式转换 T1 在不接受该类型但接受某些类型的上下文中使用 其他类型T2;特别:
- 当调用以 T2 作为参数声明的函数时,表达式用作参数时;
- 当表达式用作操作数时,运算符需要 T2;
- 初始化 T2 类型的新对象时,在返回 T2 的函数中包含 return 语句;
- 当表达式用于 switch 语句时(T2 是整数类型);
- 当表达式用于 if 语句或循环时(T2 为 bool)。
答:
std::optional
没有任何用于隐式转换为 的工具。(允许隐式转换通常被认为是一个坏主意,因为这是一个整数类型,所以类似的东西会编译并做完全错误的事情。bool
bool
bool
int i = opt
std::optional
确实有一个到 bool 的“上下文转换”,其定义看起来类似于强制转换运算符:.这不能用于隐式转换;它仅适用于预期的“上下文”为布尔值的某些特定情况,例如 if 语句的条件。explicit operator bool()
你想要的是.opt.has_value()
来自 C++ 文档:
当 optional 类型的对象< T > 在上下文中转换为 bool 时, 如果对象包含值,则转换返回 true,如果对象包含值,则返回 false 如果它不包含值。
在此处阅读有关内容相关转化的信息:
在以下上下文中,类型 bool 是预期的,隐式 如果声明 bool t(e);结构良好 (即显式转换函数,例如显式 T::运算符 bool() 常量;被考虑)。这种表达式 e 被称为 在上下文中转换为布尔值。
- if、while、for 的控制表达式;
- 内置逻辑运算符 !、&& 和 ||;
- 条件运算符的第一个操作数 ?:;
- static_assert声明中的谓语;
- noexcept 说明符中的表达式;
- 显式说明符中的表达式;
您可以执行以下操作:
bool f() {
std::optional<int> opt;
return opt || false;
}
因为上下文转换发生在内置逻辑运算符的情况下,但上下文转换不包括语句,并且本身没有隐式转换为 .return
std::optional
bool
因此,最好使用 std::optional<T>::has_value:
bool f() {
std::optional<int> opt;
return opt.has_value();
}
评论
return {opt}
return bool{opt};
return {opt};
return static_cast<bool>(opt);
return bool{opt};
has_value
return !!pot;
has_value
这是因为不支持将 std::optional 隐式转换为 bool:https://en.cppreference.com/w/cpp/utility/optional/operator_bool
constexpr 显式运算符 bool() const noexcept;
您必须显式转换为 bool as 或简单地改用。bool(opt)
opt.has_value()
评论
这并不是关于隐式转换,而是关于初始化的类型。
可选的是一个显式的转换函数,即
explicit operator bool() const;
从 N4849 [class.conv.fct]/p2
转换函数可以是显式的 (9.2.2),在这种情况下,它仅被视为用户定义的转换 用于直接初始化。
以上意味着这些情况会使用转换函数: [dcl.init]/p16
发生的初始化 (16.1) - 对于作为括号的表达式列表或支撑初始化列表的初始值设定项, (16.2) — 对于 new-initializer (7.6.2.7), (16.3) — 在static_cast表达式 (7.6.1.8) 中, (16.4) — 在函数表示法类型转换 (7.6.1.3) 中,以及 (16.5) — 在条件的 braced-init-list 形式中,称为直接初始化。
但是,这些情况不会使用转换函数: [dcl.init]/p15
以 = 形式发生的初始化 brace-or-equal-initializer 或条件 (8.5) 以及参数 传递、函数返回、抛出异常 (14.2)、处理 异常 (14.4) 和成员初始化 (9.4.1) 称为 复制初始化。
问题中的示例属于复制初始化情况,不使用 optional 的转换函数。
评论
运算符 bool()
是显式
的。std::optional