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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With