将流隐式转换为bool

时间:2016-11-27 11:54:55

标签: c++ c++11 language-lawyer

拿这个玩具代码:

#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;
}

您将获得以下反直觉结果:if(!is)编译,if(is==false)给出

  

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

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

标准说(根据this answer):

  

依赖于隐式布尔转换的有效C ++ 2003代码   无法使用本国际标准进行编译。这样的转换   发生在以下情况:

     
      
  • 将值传递给采用bool类型参数的函数;

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

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

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

  •   
  • 初始化一个const bool&amp;这会绑定到临时的。

  •   

据我所知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;
}

这里运营商的存在!()无关紧要。

2 个答案:

答案 0 :(得分:8)

std::ifstream继承的operator boolmarked 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

如果您想知道为什么if (is)和类似语句编译,那是因为转化的ifwhile等有特殊规则:explicit关键字被忽略了!

if (is);                        // ok
while (is)                      // ok
bool b = static_cast<bool>(is); // ok

请注意,最后一个案例是因为你明确想要一个bool而编译的。

从技术上讲,!is可以正常工作,因为您明确想要一个bool,但std::ifstream有一个继承的operator!,因此调用该运算符而不是对bools运行的默认operator!

if (!is);     // ok
bool b = !is; // ok

答案 1 :(得分:4)

!is有效,因为std::basic_ios是流的基类之一,已定义operator!()

所以这根本不是转换,而是调用is.operator!()