Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing "enum: int64_t" value to std::ostringstream truncates it to int

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.

like image 960
Violet Giraffe Avatar asked Mar 01 '19 19:03

Violet Giraffe


1 Answers

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

like image 69
Violet Giraffe Avatar answered Oct 28 '22 09:10

Violet Giraffe