以下代码在Visual Studio 2008中编译,但在Visual Studio 2013及更高版本中失败.
std::string str("foo"); std::stringstream ss(str); float f = 0; if ((ss >> f) == false) std::cout << "Parse error\n";
错误消息是
错误C2678:二进制'==':找不到哪个运算符带有'std :: basic_istream>'类型的左操作数(或者没有可接受的转换)
并通过以下更改成功修复:
if (!(ss >> f)) std::cout << "Parse error\n";
我不太了解这一点.我的问题是,ios
涉及哪些运算符或强制转换或可能是 标志,允许流读取首先被评估为布尔值,然后为什么缺少一个operator==
中断呢?
自C++ 11以来,两种行为发生了变化
std :: basic_ios :: operator bool的行为发生了变化.
operator void*() const; (1) (until C++11) explicit operator bool() const; (2) (since C++11)
注意,因为C++ 11 operator bool()
被声明为explicit
; 但对于if ((ss >> f) == false)
,ss
(即返回值(ss >> f)
)需要是隐式转换为bool
(与相比false
),这是不允许的.
空指针常量的定义已更改.
在使用C++ 11之前operator void*()
并没有explicit
(在C++ 11之前没有这种显式的用户定义转换),在C++ 11之前,空指针常量定义为:
整数类型的整数常量表达式rvalue,其计算结果为零(直到C++ 11)
这意味着false
可以用作空指针常量.因此ss
可以隐式转换为void*
然后与false
(与空指针)进行比较.
从C++ 11开始,空指针常量定义为:
一个值为零的整数文字,或者是一个类型的prvalue
std::nullptr_t
(从C++ 11开始)
而false
不是再次; 它不是整数文字.
因此,由于这两个更改,if ((ss >> f) == false)
将无法在C++ 11及更高版本中使用.
另一方面,if (!(ss >> f))
工作正常,因为有std :: basic_ios :: operator!(对于它来说,在C++ 11之前和之后).
bool operator!() const;
true
如果关联的流上发生错误,则返回.具体来说,true
如果设置了badbit或failbit ,则返回rdstate()
.
顺便说一句:由于C++ 11,即使没有std::basic_ios::operator!
,explicit operator bool() const
也可以if (!(ss >> f))
很好地工作,因为在上下文转换的上下文中,explicit
考虑了用户定义的转换; 即ss
可以在上下文中转换bool
为operators !
.