【问题标题】:Writing "enum: int64_t" value to std::ostringstream truncates it to int将 "enum: int64_t" 值写入 std::ostringstream 会将其截断为 int
【发布时间】:2019-03-01 19:58:19
【问题描述】:

此代码在使用 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 警告级别之后,我才发现了原因:

警告 C4305:'argument':从 'main::Enum' 截断到 'int'

但是为什么会这样呢?事实上,调试器确认调用了int 重载而不是long long,但为什么呢?以及如何在通用代码中规避这一点?我可以将muchos_digitos 转换为int64_t,但我收到的值为typename T。我可以弄清楚它是一个枚举,但我怎么知道它是一个强类型枚举,我能找出它的底层类型吗?我不认为这是直接可能的......

在 GCC 下输出是正确的,但我需要代码与 GCC、clang 和 MSVC 的所有三个一起工作。

Online demo

P。 S. 最初没有为我的项目设置 /W4 是一个错误。我建议每个人将此级别与 MSVC 和 -pedantic-errors 与 GCC / clang 一起使用,当您在编写代码时在编译时注意到它时,它确实可以节省您处理奇怪错误和令人惊讶的行为的时间。

【问题讨论】:

  • 真正奇怪的是,如果我将鼠标悬停在
  • 不是关于 为什么 的答案,但您可以使用 stackoverflow.com/questions/11421432/… 中的方法以与模板一起使用的方式解决此问题
  • 使用C++时,最好使用标准C++头文件,包括“C++包装的C”头文件,避免使用标准C头文件。所以不要使用&lt;stdint.h&gt;,而是使用&lt;cstdint&gt;
  • 理由是 C++ 包装的 C 头文件将符号放在 std 命名空间中,删除一些 C 宏并改用 C++ 内联函数,并提供正确重载的 C++ 版本而不是非重载的 C 版本。
  • 向 MSVC 提交错误。这应该提升到底层类型。

标签: c++ enums overloading c++17


【解决方案1】:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    相关资源
    最近更新 更多