"不到"ifstream与GCC 4对6的比较

Bug*_*ger 5 c++ gcc c++11

我只是偶然发现了这段代码:

std::string export_str = "/path/to/file";
std::ofstream export(export_str.c_str());
if (export < 0) {
    std::cout << "Unable to export" << std::endl;
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

这可以用GCC 4.9.3进行编译和运行,但是在GCC 6.1.1上会出现这个错误:

error: no match for ‘operator<’ (operand types are ‘std::ofstream {aka std::basic_ofstream<char>}’ and ‘int’)
 if (export < 0) {
     ~~~~~~~~~~~^~~
Run Code Online (Sandbox Code Playgroud)

我试图GCC 6:
-std=c++98(不编译)
-std=c++03(不编译)
-std=c++11(也编译)

编辑: 但是,在GCC 4中它仍然可以编译-std=c++11.这个具体事实也在下面的答案中解释.:)

所以我猜这个标准有所改变.

经过一番研究后,我将代码更改为:

std::string export_str = "/path/to/file";
std::ofstream export(export_str.c_str());
if (export.fail()) { // <-- related change
    std::cout << "Unable to export" << std::endl;
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

编译并运行良好,但我没有找到这个变化的好解释,可能是由于没有提出一个好的搜索词组合.

所以我的问题不是 "如何检查ofstream的有效性".已经有一些或多或少令人满意的答案("或多或少"因为问题似乎有点复杂).
在这里这里这里.

我的问题解释GCC 4和GCC 6之间关于编译(export < 0)上述代码中的内容所做的更改.

谢谢你的任何指示.

Bau*_*gen 12

在预C++ 11之前,标准流可以隐式转换为void*,NULL指示坏流和非NULL流.

所以你得到的是(void*)export和之间的指针比较(void*)0,这是合法的(在"应该编译"的意义上)和非感性的.

在C++ 11中,流转换void*为由显式转换替换bool,它仍然允许像以前一样检查流的状态,但是使诸如你的无意义代码成为非法的.

这里重要的是从隐式转换到显式转换btw.如果新的转换bool是隐式的,代码仍然会编译并进行(bool) export < 0比较.但是通过显式转换,这需要强制转换.


关于gcc4和gcc6之间的区别:libstdc ++ 4.x中的流在这方面不符合C++ 11.在版本5中修复/实现了C++ 11流转换,以及包括流和SSO的移动语义在内的相当多的C++ 11缺点.

gcc4只是不完整的C++ 11功能,在这种情况下,它遵循旧规则,它不应该.


为了完整起见:正如评论中已经提到的那样,export是一个关键字,不应该用作名称.