7

This code behaves in an unexpected way with MSVC compiler (v141 toolset, /std:c++17):

#include <iostream>
#include <limits>
#include <sstream>
#include <stdint.h>

int main() {
    std::ostringstream ss;
    enum Enum : int64_t {muchos_digitos = std::numeric_limits<int64_t>::max() - 1000};
    ss << muchos_digitos;
    std::cout << ss.str();
    return 0;
}

Specifically, it prints "-1001". It is only after much head scratching and enabling /W4 warning level that I discovered the cause:

warning C4305: 'argument': truncation from 'main::Enum' to 'int'

But why does it happen? Indeed, the debugger confirms that int overload is called instead of long long, but why? And how can I circumvent this in generic code? I could cast muchos_digitos to int64_t, but I receive the value as typename T. I can figure out that it's an enum, but how can I know that it's a strongly typed enum, and can I find out its underlying type? I don't think it's directly possible...

The output is correct under GCC, but I need the code to work with all three of GCC, clang and MSVC.

Online demo

P. S. It was a mistake that /W4 was not set for my project in the first place. I recommend everyone to use this level with MSVC and -pedantic-errors with GCC / clang, it really saves you time with bizzare errors and surprising behavior when you notice it at compile time as you write the code.

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335
  • 1
    What is really bizarre is that if I hover over the << intelisense tells me it has picked the long long overload. Must be a bug but I'm not finding anything reported on it. – NathanOliver Mar 01 '19 at 20:11
  • 1
    Not an answer as to _why_, but you can solve this issue in a way that works with templates using methods from https://stackoverflow.com/questions/11421432/how-can-i-output-the-value-of-an-enum-class-in-c11 – rtpax Mar 01 '19 at 20:15
  • @rtpax: thanks, didn't know about `std::underlying_type`! – Violet Giraffe Mar 01 '19 at 20:18
  • 1
    When using C++, it is best to use standard C++ header files, including the "C++ wrapped C" header files, and avoid standard C header files. So rather than `` instead use ``. – Eljay Mar 01 '19 at 20:32
  • @Eljay: thanks. I've heard that recommendation many times, but in my 8+ years of programming I never understood the rationale. To be honest, these "wrapped" headers look suspicious to me. – Violet Giraffe Mar 01 '19 at 20:34
  • 3
    The rationale being that the C++ wrapped C header files put the symbols in the `std` namespace, remove some C macros and use C++ inline functions instead, and provide properly overloaded C++ version instead of the non-overloaded C version. – Eljay Mar 01 '19 at 20:46
  • @Eljay: I have never noticed the benefits. Whenever I needed an overload, the "old" header also had it. And the plain .h headers are almost always included anyway by some third-party libraries, or maybe even by the platform headers, at least on Windows. Just my personal experience with a bunch of projects. I'm not saying you're wrong; I know you're right. But to me, including "new" headers seems redundant, just more stuff for the compiler to parse and more symbols to pollute the namespace. – Violet Giraffe Mar 01 '19 at 20:49
  • @Eljay: C++ projects usually end up indirectly including the good old C header files anyway, so it really doesn't matter. In fact, most C++ code in the wild is written expecting good old C functions like `strlen()` to be in global scope, which is only guaranteed to be portable if you include the good old C header files. – John Zwinck Mar 01 '19 at 23:29
  • 4
    File a bug with MSVC. This should promote to the underlying type. – T.C. Mar 02 '19 at 06:12
  • You want to prefer `` in the same way you don't want to use `using namespace std;`. – L. F. Sep 08 '19 at 08:27
  • 1
    You got MS feedback in https://developercommunity.visualstudio.com/content/problem/475488/wrong-ostringstreamoperator-overload-selected-for.html that this is a bug and it is fixed in VS2019. Can you please post this as an answer here and accept it!? Thanks. – Werner Henze Feb 16 '20 at 17:02

1 Answers1

1

This was confirmed to be a bug by the Microsoft team and it's now fixed in VS 2019: https://developercommunity.visualstudio.com/content/problem/475488/wrong-ostringstreamoperator-overload-selected-for.html

Violet Giraffe
  • 32,368
  • 48
  • 194
  • 335