拿这个玩具代码:
#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;
}
这里运营商的存在!()无关紧要。
答案 0 :(得分:8)
std::ifstream
继承的operator bool
是marked 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)
和类似语句编译,那是因为转化的if
,while
等有特殊规则: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!()
。