简体   繁体   English

将流运算符>>评估为布尔值

[英]Evaluating stream operator >> as boolean

The following code compiles in Visual Studio 2008 but fails in Visual Studio 2013 and later. 以下代码在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";

The error message is 错误消息是

error C2678: binary '==' : no operator found which takes a left-hand operand of type 'std::basic_istream>' (or there is no acceptable conversion) 错误C2678:二进制'==':找不到哪个运算符带有'std :: basic_istream>'类型的左操作数(或者没有可接受的转换)

and is successfully fixed by changing as follows: 并通过以下更改成功修复:

if (!(ss >> f))
    std::cout << "Parse error\n";

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? 我的问题是,涉及哪些运算符或强制转换或ios标志允许流读取首先被评估为布尔值,然后为什么缺少operator==打破它?

Two behaviors changed since C++11. 自C ++ 11以来,两种行为发生了变化

  1. The behavior of std::basic_ios::operator bool changed. std :: basic_ios :: operator bool的行为发生了变化。

     operator void*() const; (1) (until C++11) explicit operator bool() const; (2) (since C++11) 

    Note since C++11 operator bool() is declared as explicit ; 注意,因为C ++ 11 operator bool()被声明为explicit ; but for if ((ss >> f) == false) , ss (ie the return value of (ss >> f) ) needs to be implicit converted to bool (to be compared with false ), which is not allowed. 但对于if ((ss >> f) == false)ss (即(ss >> f)的返回值)需要隐式转换为bool (与false进行比较),这是不允许的。

  2. The definition of the null pointer constant changed. 空指针常量的定义已更改。

    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之前,可以使用operator void*()并且它不是explicit (在C ++ 11之前没有这种显式的用户定义转换 ),在C ++ 11之前,空指针常量定义为:

    an integral constant expression rvalue of integer type that evaluates to zero (until C++11) 整数类型的整数常量表达式rvalue,其计算结果为零(直到C ++ 11)

    which means false could be used as a null pointer constant. 这意味着false可以用作空指针常量。 So ss could be implicitly converted to void* and then compared with false (as the null pointer). 所以ss可以隐式转换为void* ,然后与false比较(作为空指针)。

    From C++11, the null pointer constant is defined as: 从C ++ 11开始,空指针常量定义为:

    an integer literal with value zero, or a prvalue of type std::nullptr_t (since C++11) 一个值为零的整数文字,或者类型为std::nullptr_t的prvalue(自C ++ 11起)

    while false is not again; false不再是; it's not an integer literal . 它不是整数文字

So, because of these two changes, if ((ss >> f) == false) won't work in C++11 and later. 因此,由于这两个变化, if ((ss >> f) == false)在C ++ 11及更高版本中不起作用。

On the other hand, if (!(ss >> f)) works fine because there's std::basic_ios::operator! 另一方面, if (!(ss >> f))工作正常,因为有std :: basic_ios :: operator! (both before and after C++11) for it. (对于它来说,在C ++ 11之前和之后)。

 bool operator!() const; 

Returns true if an error has occurred on the associated stream. 如果关联的流上发生错误,则返回true Specifically, returns true if badbit or failbit is set in rdstate() . 具体来说,如果在rdstate()设置了rdstate()或failbit,则返回true

BTW: Since C++11, even without std::basic_ios::operator! BTW:从C ++ 11开始,即使没有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; explicit operator bool() const也可以使if (!(ss >> f))运行良好,因为在上下文转换的上下文中,考虑了explicit用户定义转换; ie ss could be contextually converted to bool for operators ! ss可以在上下文中转换为booloperators ! .

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM