evpo
evpo

Reputation: 2531

Implicit cast to bool of basic_istream/ifstream/ofstream doesn't work in Visual Studio 2013

The code below compiles in VS 2012 but not in VS 2013

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

In VS 2013 you get this compilation error:

binary '!=' no operator found which takes a left-hand operand of type 'std::ofstream' (or there is no acceptable conversion)

I looked at the headers and in <xiobase> and I found the following:

VS2012

ios_base::operator void *() const;

VS2013

operator void *() const has been removed and the operator bool with explicit was added instead:

ios_base::explicit operator bool() const;

Now my questions:

  1. I couldn't find any information about this change in the internet. Do you know if there is an official article about this change anywhere?
  2. I have legacy code where if(stm != NULL) is used a lot. For unrelated reasons it's preferable not to change the code. Is there a way to make it compile in VS 2013 without changing it? I couldn't find any conditional compilation directives that could restore operator void* or remove explicit from operator bool().

PS: gcc 4.9.0 still has operator void*() const. So it will not have this problem.

UPDATE:

To make my legacy code compile I implemented the following overloads as it was suggested:

#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);
}

In my case the char value type was enough and the second parameter is int because something that is not NULL is not supported anyway.

Upvotes: 3

Views: 2087

Answers (3)

Marius Bancila
Marius Bancila

Reputation: 16338

The operator is defined in section 27.5.5 Class template basic_ios.

27.5.5.1 Overview

explicit operator bool() const;

And then

27.5.5.4 basic_ios flags functions

explicit operator bool() const;

Returns: !fail().

Upvotes: 0

Michael Burr
Michael Burr

Reputation: 340366

C++11 requires some boolean conversions to be explicit that used to be implicit. This is noted in Appendix C about compatibility with C++03:

C.2.15 Clause 27: Input/output library [diff.cpp03.input.output]

27.7.2.1.3, 27.7.3.4, 27.5.5.4

Change: Specify use of explicit in existing boolean conversion operators

Rationale: Clarify intentions, avoid workarounds.

Effect on original feature: Valid C++ 2003 code that relies on implicit boolean conversions will fail to compile with this International Standard. Such conversions occur in the following conditions:

  • passing a value to a function that takes an argument of type bool;
  • using operator== to compare to false or true;
  • returning a value from a function with a return type of bool;
  • initializing members of type bool via aggregate initialization;
  • initializing a const bool& which would bind to a temporary.

Upvotes: 6

Some programmer dude
Some programmer dude

Reputation: 409404

If you have a lot of legacy code, you could probably add a custom operator!= (and operator==) function which takes the correct arguments:

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

Upvotes: 1

Related Questions