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)
在这里,运营商!()的存在是无关紧要的.
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)