【问题标题】:Evaluating stream operator >> as boolean将流运算符 >> 评估为布尔值
【发布时间】:2017-05-24 15:50:12
【问题描述】:

以下代码在 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++ c++11 visual-c++ type-conversion language-lawyer


    【解决方案1】:

    自 C++11 以来,两种行为发生了变化。

    1. 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 &gt;&gt; f) == false)ss(即(ss &gt;&gt; f)的返回值)需要隐式转换为bool(与false比较),这是不允许的。

    2. 空指针常量的定义发生了变化。

      在C++11之前可以使用operator void*()而不是explicit(在C++11之前没有这样的explicit user-defined conversion),在C++11之前the null pointer constant定义为:

      整数类型的整数常量表达式右值,其计算结果为零 (直到 C++11)

      这意味着false 可以用作空指针常量。所以ss 可以隐式转换为void*,然后与false(作为空指针)进行比较。

      从C++11开始,空指针常量定义为:

      值为 0 的整数文字,或类型为 std::nullptr_t 的纯右值 (C++11 起)

      虽然false 不再存在;这不是integer literal

    因此,由于这两个更改,if ((ss &gt;&gt; f) == false) 将无法在 C++11 及更高版本中运行。

    另一方面,if (!(ss &gt;&gt; f)) 工作正常,因为它有 std::basic_ios::operator!(在 C++11 之前和之后)。

    bool operator!() const;
    

    如果关联流发生错误,则返回 true。 具体来说,如果在 rdstate() 中设置了 badbit 或 failbit,则返回 true

    BTW:由于C++11,即使没有std::basic_ios::operator!explicit operator bool() const也可以使if (!(ss &gt;&gt; f))工作得很好,因为在contextual conversion的上下文中,explicit考虑了用户定义的转换;即ss 可以根据上下文转换为bool 以获取operators !

    【讨论】:

    • 值得一提的是,即使operator bool 被标记为explicitif(foo)if(!foo) 仍然有效,这是由于bool 运算符的显式转换的少数例外之一。示例here。我相信这被称为上下文转换,参见例如this blog post.
    • NULL 是一个扩展为 a 空指针常量的宏,不是“空指针常量”,也不是术语“空指针常量”的同义词。
    猜你喜欢
    • 1970-01-01
    • 2013-11-11
    • 2011-07-31
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-28
    • 2016-02-12
    • 1970-01-01
    相关资源
    最近更新 更多