c++c++11visual-c++c++17msvc12

auto open_flags = std::ios::binary; seems to produce the wrong type in MSVC. Is it a bug?


This c++ code compiles fine with gcc, icc, and clang, but fails with MSVC:

#include <ios>

int main()
{
    auto open_flags = std::ios::binary;
    open_flags |= std::ios::app;

    return 0;
}
(6): error C2678: binary '|=': no operator found which takes a left-hand operand of type 'std::_Iosb::_Openmode' (or there is no acceptable conversion)

https://godbolt.org/z/999fffPEx

Changing the code to this gives a more helpful error message:

#include <ios>

int main()
{
    auto open_flags = std::ios::binary;
    open_flags = open_flags | std::ios::app;

    return 0;
}
(6): error C2440: '=': cannot convert from 'int' to 'std::_Iosb::_Openmode'

And this compiles fine:

#include <ios>

int main()
{
    auto open_flags = std::ios::binary | std::ios::out;
    open_flags = open_flags | std::ios::app;

    return 0;
}

This looks like incorrect behaviour to me. Like MSVC has implemented the | operator with return type int instead of ios::openmode.

It's also worth noting that the original code compiles if I use std::ios::openmode instead of auto, presumably through implicit conversion.

Is this an MSVC bug, or am I missing something? Standards references welcome!


Solution

  • It's a MSVC bug.

    According to the standard:

    1. binary has type std::ios_base::openmode ([ios.base.general]);
    2. std::ios_base::openmode is a bitmask type ([ios.openmode]).

    But on MSVC:

    1. binary has an enum type (the internal type _Openmode), but std::ios_base::openmode is int.
    2. _Openmode is not a bitmask type (and thus only built-in operators |, &, ^, ~ are applicable).

    Please file a bug report (or two) at https://github.com/microsoft/STL.