评估流运算符>>作为布尔值 [英] Evaluating stream operator >> as boolean
问题描述
以下代码在Visual Studio 2008中编译,但在Visual Studio 2013及更高版本中失败.
The following code compiles in Visual Studio 2008 but fails in Visual Studio 2013 and later.
std::string str("foo");
std::stringstream ss(str);
float f = 0;
if ((ss >> f) == false)
std::cout << "Parse error\n";
错误消息是
错误C2678:二进制'==':未找到需要左手操作的运算符 类型'std :: basic_istream>'的操作数(或 没有可接受的转换)
error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::basic_istream>' (or there is no acceptable conversion)
,并通过以下更改成功修复:
and is successfully fixed by changing as follows:
if (!(ss >> f))
std::cout << "Parse error\n";
我对此不太了解.我的问题是,涉及什么运算符或强制转换或ios
标志,这些标志首先允许将读取的流评估为布尔值,然后为什么没有operator==
会破坏它呢?
I'm not understanding this well. My question is, what operator or cast or maybe ios
flags are involved that allow the stream read to be evaluated as a boolean in the first place, and then why does the lack of an operator==
break it?
推荐答案
自C ++ 11以来发生了两种变化.
Two behaviors changed since C++11.
The behavior of std::basic_ios::operator bool changed.
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
比较).
Note since C++11 operator bool()
is declared as explicit
; but for if ((ss >> f) == false)
, ss
(i.e. the return value of (ss >> f)
) needs to be implicit converted to bool
(to be compared with false
), which is not allowed.
空指针常量的定义已更改.
在使用C ++ 11 operator void*()
之前,不能使用explicit
(在C ++ 11之前,没有这样的空指针常量定义为:
Before C++11 operator void*()
could be used and it's not explicit
(before C++11 there's no such explicit user-defined conversion), and before C++11 the null pointer constant is defined as:
整数类型的整数常量表达式右值,其值为零 (直到C ++ 11)
an integral constant expression rvalue of integer type that evaluates to zero (until C++11)
表示false
可用作空指针常量.因此,可以将ss
隐式转换为void*
,然后与false
(作为空指针)进行比较.
which means false
could be used as a null pointer constant. So ss
could be implicitly converted to void*
and then compared with false
(as the null pointer).
从C ++ 11开始,空指针常量定义为:
From C++11, the null pointer constant is defined as:
整数文字,其值为零,或类型为
std::nullptr_t
的prvalue (自C ++ 11起)
an integer literal with value zero, or a prvalue of type
std::nullptr_t
(since C++11)
而false
不再出现;它不是整数文字.
因此,由于这两个更改,if ((ss >> f) == false)
在C ++ 11和更高版本中将不起作用.
So, because of these two changes, if ((ss >> f) == false)
won't work in C++11 and later.
另一方面,if (!(ss >> f))
可以正常工作,因为其中有 std :: basic_ios :: operator!(在C ++ 11之前和之后).
On the other hand, if (!(ss >> f))
works fine because there's std::basic_ios::operator! (both before and after C++11) for it.
bool operator!() const;
如果关联的流上发生错误,则返回true
.
具体来说,如果在rdstate()
中设置了badbit或failbit,则返回true
.
Returns true
if an error has occurred on the associated stream.
Specifically, returns true
if badbit or failbit is set in rdstate()
.
BTW:由于C ++ 11,即使没有std::basic_ios::operator!
,explicit operator bool() const
也可以使if (!(ss >> f))
正常工作,因为在
BTW: Since C++11, even without std::basic_ios::operator!
, explicit operator bool() const
could also make if (!(ss >> f))
works well, because in the context of contextual conversion, explicit
user-defined conversion is considered; i.e. ss
could be contextually converted to bool
for operators !
.
这篇关于评估流运算符>>作为布尔值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!