将对象转换为 bool 时,显式说明符似乎不起作用

explicit specifier doesn't seem to work when converting an object to bool

我最近在学习 C++,我注意到一个 example on cppreference,其中一部分是这样的:

struct B
{
    explicit B(int) { }
    explicit operator bool() const { return true; }
};

int main()
{
    B b2(2);       // OK: direct-initialization selects B::B(int)
    if (b2) ;      // OK: B::operator bool()
}

implicit conversions的介绍告诉我"when the expression is used in an if statement or a loop"这个表达式(b2)的结果会被隐式转换成bool类型。

还有explicit specifier的介绍告诉我如果"a conversion function is explicit, it cannot be used for implicit conversions".

既然b2会在if(b2)中进行隐式转换,而转换函数是explicit,那么if(b2)怎么就ok了呢?

Contextual conversion很特别;自 C++11 起,explicit 转换函数将在上下文转换中考虑。

(强调我的)

(since C++11)

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; (since C++20)
  • the predicate of a contract attribute. (since C++20)

这意味着对于 if (b2)b2 将被 B::operator bool() 隐式转换为 bool,即使它被声明为 explicit

阅读further in your own link。即使 explicit 次转换也会隐式发生上下文转换:

Contextual conversions

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;
  • the predicate of a contract attribute.