Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 526
evpo Avatar asked Dec 20 '25 23:12

evpo


2 Answers

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.
like image 197
Michael Burr Avatar answered Dec 23 '25 12:12

Michael Burr


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);
like image 43
Some programmer dude Avatar answered Dec 23 '25 12:12

Some programmer dude



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!