将 "enum: int64_t" 值写入 std::ostringstream 会将其截断为 int
Writing "enum: int64_t" value to std::ostringstream truncates it to int
此代码在 MSVC 编译器(v141 工具集,/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;
}
具体来说,它打印“-1001”。经过多次摸索和启用 /W4
警告级别后,我才发现原因:
warning C4305: 'argument': truncation from 'main::Enum' to 'int'
但为什么会这样呢?实际上,调试器确认调用了 int
重载而不是 long long
,但为什么呢?我怎样才能在通用代码中规避这一点?我可以将 muchos_digitos
转换为 int64_t
,但我收到的值是 typename T
。我可以弄清楚它是一个枚举,但是我怎么知道它是一个强类型的枚举,我能找出它的底层类型吗?我不认为这是直接可能的...
在 GCC 下输出是正确的,但我需要代码才能与 GCC、clang 和 MSVC 这三个一起工作。
P. S. 一开始没有为我的项目设置 /W4 是个错误。我建议大家将此级别与 MSVC 一起使用,-pedantic-errors
与 GCC / clang 一起使用,当您在编写代码时在编译时注意到它时,它确实可以为您节省奇怪的错误和令人惊讶的行为的时间。
这已被 Microsoft 团队确认为错误,现已在 VS 2019 中修复:https://developercommunity.visualstudio.com/content/problem/475488/wrong-ostringstreamoperator-overload-selected-for.html
此代码在 MSVC 编译器(v141 工具集,/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;
}
具体来说,它打印“-1001”。经过多次摸索和启用 /W4
警告级别后,我才发现原因:
warning C4305: 'argument': truncation from 'main::Enum' to 'int'
但为什么会这样呢?实际上,调试器确认调用了 int
重载而不是 long long
,但为什么呢?我怎样才能在通用代码中规避这一点?我可以将 muchos_digitos
转换为 int64_t
,但我收到的值是 typename T
。我可以弄清楚它是一个枚举,但是我怎么知道它是一个强类型的枚举,我能找出它的底层类型吗?我不认为这是直接可能的...
在 GCC 下输出是正确的,但我需要代码才能与 GCC、clang 和 MSVC 这三个一起工作。
P. S. 一开始没有为我的项目设置 /W4 是个错误。我建议大家将此级别与 MSVC 一起使用,-pedantic-errors
与 GCC / clang 一起使用,当您在编写代码时在编译时注意到它时,它确实可以为您节省奇怪的错误和令人惊讶的行为的时间。
这已被 Microsoft 团队确认为错误,现已在 VS 2019 中修复:https://developercommunity.visualstudio.com/content/problem/475488/wrong-ostringstreamoperator-overload-selected-for.html