【问题标题】:Implicit cast to bool of basic_istream/ifstream/ofstream doesn't work in Visual Studio 2013隐式转换为 basic_istream/ifstream/ofstream 的 bool 在 Visual Studio 2013 中不起作用
【发布时间】:2014-04-23 06:31:50
【问题描述】:

以下代码在 VS 2012 中编译,但在 VS 2013 中不编译

std::ofstream stm;
if(stm != NULL)
{
}

在 VS 2013 中,您会收到以下编译错误:

二进制 '!=' 未找到接受 'std::ofstream' 类型左侧操作数的运算符(或没有可接受的转换)

我查看了标题并在<xiobase> 中发现了以下内容:

VS2012

ios_base::operator void *() const;

VS2013

operator void *() const 已被删除,而是添加了带显式的运算符 bool:

ios_base::explicit operator bool() const;

现在我的问题:

  1. 我在 Internet 上找不到有关此更改的任何信息。您是否知道任何地方是否有关于此更改的官方文章?
  2. 我有很多使用 if(stm != NULL) 的遗留代码。由于不相关的原因,最好不要更改代码。有没有办法让它在 VS 2013 中编译而不改变它?我找不到任何可以恢复运算符 void* 或从运算符 bool() 中删除 explicit 的条件编译指令。

PS:gcc 4.9.0 仍然有operator void*() const。所以就不会有这个问题了。

更新:

为了编译我的遗留代码,我按照建议实现了以下重载:

#include <xiosbase>

bool operator==(const std::basic_ios<char, char_traits<char>> &stm, int null_val)
{
    return static_cast<bool>(stm) == null_val;
}

bool operator==(int null_val, const std::basic_ios<char, char_traits<char>> &stm)
{
    return operator==(stm, null_val);
}

bool operator!=(int null_val, const std::basic_ios<char, char_traits<char>> &stm)
{
    return !operator==(stm, null_val);
}

bool operator!=(const std::basic_ios<char, char_traits<char>> &stm, int null_val)
{
    return !operator==(stm, null_val);
}

在我的情况下,char 值类型就足够了,第二个参数是 int,因为无论如何都不支持非 NULL 的东西。

【问题讨论】:

  • 这个变化是 C++11 规范的一部分,所以应该很容易找到关于它的文章。如果没有别的,请阅读规范草案。
  • @JoachimPileborg 是的,en.cppreference.com/w/cpp/io/basic_ios/operator_bool 是一篇非常有用的文章。它说 operator void *() "直到 C++11" 和显式 operator bool() "since C++11"。所以看起来这是一个已知的变化
  • 我怀疑 GCC 4.9 的 libstdc++ 在 C++11 模式下编译时有 operator void*。我在the GCC 4.9 ostream header 中找不到它,其中包含operator bool...
  • @rubenvb 看这个演示goo.gl/yIHOXx
  • 嗯,这看起来是错误的... C++11 27.5.5.1std::basic_ios 中没有operator void*() const。但是VS2013 still has it,尽管它们显示了一个获取流对象地址的示例。

标签: c++ visual-studio-2012 c++11 visual-studio-2013


【解决方案1】:

C++11 需要一些布尔转换是显式的,而过去是隐式的。这在附录 C 中提到了与 C++03 的兼容性:

C.2.15 第 27 条:输入/输出库 [diff.cpp03.input.output]

27.7.2.1.3、27.7.3.4、27.5.5.4

更改:指定在现有布尔转换运算符中使用显式

理由:明确意图,避免变通方法。

对原始功能的影响:依赖于隐式布尔转换的有效 C++ 2003 代码将无法使用本国际标准进行编译。此类转换发生在以下情况:

  • 将值传递给采用 bool 类型参数的函数;
  • 使用 operator== 比较 false 或 true;
  • 从返回类型为 bool 的函数返回值;
  • 通过聚合初始化来初始化 bool 类型的成员;
  • 初始化一个 const bool& 将绑定到一个临时对象。

【讨论】:

  • 在 MSVC 2015 中 if(stm) 编译,但 if(stm == true) 失败。为什么只有第二个符合“隐式布尔转换”的条件?这可能是 MSVC 错误吗?
【解决方案2】:

如果您有很多遗留代码,您可能会添加一个自定义 operator!=(和 operator==)函数,该函数采用正确的参数:

bool operator!=(std::basic_ios const& ios, const void* ptr);
bool operator!=(const void* ptr, std::basic_ios const& ios);

【讨论】:

  • std:: 类型的重载运算符,是否允许?
  • @MSalters 我们在制作插入器/提取器时一直这样做 (operator&lt;&lt;()/operator&gt;&gt;())。为什么不应该呢?
  • @0x499602D2:因为在这种情况下,重载包括您自己的一种类型。这显然不能与 std:: 提供的重载冲突。
【解决方案3】:

运算符在27.5.5 Class template basic_ios 部分中定义。

27.5.5.1 概述

explicit operator bool() const;

然后

27.5.5.4 basic_ios 标志函数

explicit operator bool() const;

返回:!fail()。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 2014-10-10
    相关资源
    最近更新 更多