将流隐式转换为bool

Ofe*_*lon 6 c++ language-lawyer c++11

拿这个玩具代码:

#include <iostream>
#include <fstream>

int main() {

    std::ifstream is;
    // perform read
    // ...
    if (!is) // works
        std::cout << "fail";
    if( is == false)  // error C2678
        std::cout << "fail";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

你会得到以下反直觉的结果:if(!is)编译,并if(is==false)给出

错误C2678:二进制'==':找不到哪个运算符带有'std :: ifstream'类型的左操作数(或者没有可接受的转换)

(对于VS2015 - gcc和clang中的类似错误).

标准说(根据这个答案):

依赖于隐式布尔转换的有效C++ 2003代码将无法使用此国际标准进行编译.此类转换发生在以下条件中:

  • 将值传递给带有bool类型参数的函数;

  • 使用operator ==来比较false或true;

  • 从返回类型为bool的函数返回一个值;

  • 通过聚合初始化初始化bool类型的成员;

  • 初始化一个const bool&将绑定到一个临时的.

据我所知if(is==false),明确要求失败,但怎么if(!is)没有?它不符合"隐式布尔转换"的条件吗?

这个转换为bool是否故意从标准中列出的案例中删除?也许这是一个无意的遗漏?


编辑:此代码也失败了:

int main() {

    std::ifstream is;
    // perform read
    // ...
    if (is) // works
        std::cout << "success";
    if( is == true)  // error C2678
        std::cout << "success";

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

在这里,运营商!()的存在是无关紧要的.

Rak*_*111 9

std::ifstream继承operator bool标记为explicit:

explicit operator bool() const; (2)(自C++ 11起)

这意味着没有隐式转换为bool,即所有这些表达式都失败了:

bool result = is;    // fails
bool b = is == true; // fails
if (is == false);    // fails
while (is == false); // fails
Run Code Online (Sandbox Code Playgroud)

如果你想知道为什么if (is)和类似表述编译,这是因为有特殊的规则if,while等的转换:explicit关键字被忽略!

if (is);                        // ok
while (is)                      // ok
bool b = static_cast<bool>(is); // ok
Run Code Online (Sandbox Code Playgroud)

请注意,最后一种情况是编译的,因为您明确地想要一个bool.

从技术上讲,!is可以正常工作,因为你显然想要一个bool,但是std::ifstream有一个继承的operator!,所以调用运算符而不是默认operator!操作bools:

if (!is);     // ok
bool b = !is; // ok
Run Code Online (Sandbox Code Playgroud)

  • @OfekShilon查找[*上下文转换为bool*](http://en.cppreference.com/w/cpp/language/implicit_conversion#Contextual_conversions).这是"if"等控制表达式的上下文.在这些上下文中考虑显式运算符bool. (3认同)
  • 没有明确的`运算符!它[可能有效](http://coliru.stacked-crooked.com/a/b5f1f0d91368afc3)! (2认同)