返回时不允许隐式转换


#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 语句;
  • 当表达式用于开关语句时(T2 是整型(;
  • 当表达式用于 if 语句或循环时(T2 是布尔值(。
std::optional

没有任何隐式转换为bool的工具。(允许隐式转换为bool通常被认为是一个坏主意,因为bool是一个整数类型,所以像int i = opt这样的东西会编译并做完全错误的事情。

std::optional确实有一个到 bool 的"上下文转换",其定义看起来类似于强制转换运算符:explicit operator bool()。这不能用于隐式转换;它仅适用于预期的"上下文"是布尔值的某些特定情况,例如 if 语句的条件。

你想要的是opt.has_value().

来自C++文档:

optional类型的对象在上下文中转换为布尔值时, 如果对象包含值,则转换返回 true,如果对象包含值,则返回 false 如果它不包含值。

在此处阅读有关内容相关转化的信息:

在以下上下文中,类型布尔是预期的,隐式 如果声明布尔值 t(e(,则执行转换;格式良好 (即显式转换函数,例如显式 T::运算符 bool(( const;被考虑(。这样的表达式 e 被称为 上下文转换为布尔值。

  • 如果、而、为的控制表达式;
  • 内置逻辑运算符的操作数 !, && 和 ||;
  • 条件运算符的第一个操作数 ?:;
  • static_assert声明中的谓词;
  • 不分说明符中的表达式;
  • 显式说明符中的表达式;

您可以执行以下技巧:

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();
}

这是因为不支持将 std::optional 隐式转换到布尔: https://en.cppreference.com/w/cpp/utility/optional/operator_bool

constexpr explicit operator bool(( const noexcept;

您必须显式转换为 bool 作为bool(opt)或干脆使用opt.has_value()代替。

这不是真正的隐式转换,这是关于初始化的类型。

可选的是显式转换函数,即

explicit operator bool() const; 

从 N4849 [class.conv.fct]/p2

转换

函数可能是显式的 (9.2.2(,在这种情况下,它仅被视为用户定义的转换 用于直接初始化。

以上意味着这些情况将使用转换函数: [dcl.init]/p16

发生的初始化 (16.1( — 对于作为括号表达式列表或大括号初始化列表的初始值设定项, (16.2( — 对于新初始值设定项 (7.6.2.7(, (16.3( — 在static_cast表达式 (7.6.1.8( 中, (16.4( — 在函数表示法类型转换 (7.6.1.3( 中,以及 (16.5( — 在条件的大括号初始化列表形式中称为直接初始化。

但是,这些情况不会使用转换函数: [dcl.init]/p15

以 = 形式发生的初始化 大括号或等于初始值设定项或条件 (8.5(,以及参数 传递、函数返回、引发异常 (14.2(、处理 异常 (14.4( 和成员初始化 (9.4.1( 称为 复制初始化。

问题中的示例属于复制初始化情况,不使用可选的转换函数。

相关内容

  • 没有找到相关文章

最新更新