【问题标题】:Why does casting an int to a strongly typed enum compile if it is "not within the enums range"? [duplicate]如果它“不在枚举范围内”,为什么将 int 强制转换为强类型枚举编译? [复制]
【发布时间】:2017-06-01 13:24:39
【问题描述】:

在下面的代码中,我使用static_cast 将强类型的enum 转换为int。在另一个方向上也是如此。但如果演员表int 不在enum 的范围内,它也可以工作。为什么会这样,为什么编译器没有捕捉到这个?

#include <iostream>
#include <string>

enum class Name {Hans, Peter, Georg}; // 0, 1, 2

std::string getName(Name name) {
    switch(name) {
        case Name::Hans:  return "Hans";
        case Name::Peter: return "Peter";
        case Name::Georg: return "Georg";
        default: return "not valid name";
    }
}

int main()
{
    // Cast a Name to an int, works fine.
    std::cout<< static_cast<int>( Name::Peter ) <<std::endl; // 1
    std::cout<< static_cast<int>( Name::Hans ) <<std::endl;  // 0

    // Cast an int to a Name
    std::cout<< getName(static_cast<Name>(2)) <<std::endl;   // Georg
    std::cout<< getName(static_cast<Name>(3)) <<std::endl;   // not a valid name
    // I would expect a compiler error/warning like i get here:
    // std::cout<< static_cast<int>( Name::Hans + 4 ) <<std::endl;
}

【问题讨论】:

  • 你认为编译器应该在什么基础上“捕捉”这个?据我所知,C++ 标准不需要对此进行任何诊断。
  • 添加整数值有效性检查将产生运行时开销。
  • 当我取消注释最后一行时我得到的错误是no match for ‘operator+’ (operand types are ‘Name’ and ‘int’),这与你关于枚举范围的问题没有任何关系。
  • 我希望可以选择这个,但是,clang 和 gcc 都不会为此发出警告。当您使用static_cast 时,您已经告诉编译器:我知道得更好!
  • 转换意味着通过提供它(类型系统)不能或不允许自己推断的附加信息来覆盖类型系统。编译器将隐含地相信此信息是准确的,无论它多么不可信。强制转换覆盖了一个安全系统,它们不是隐式安全的,正确使用它们的责任落在了开发者身上。

标签: c++ enums casting compiler-errors


【解决方案1】:

一方面,人们经常使用枚举来表示位标志:

enum class FontFlags { bright=0x1, bold=0x2, blink=0x4 };

现在他们希望这能奏效:

FontFlags(int(FontFlags::bold) | int(FontFlags::blink))

但当然值是 6,这是“不可能的”。

【讨论】:

  • 强类型枚举(带有enum class)不支持operator|
  • @Kevin:已更新以解决该问题。
  • 我认为这违背了这个答案的目的。如果您需要转换为 int 才能获得枚举的“不可能”值,那么您将不再拥有有效的枚举。
  • @Kevin:我试图说明为什么编译器不应该仅仅拒绝从未映射的整数构造或强制转换枚举。无论我输入6 还是bold|blink 都无关紧要 - 值是相同的,并且它必须是有效的,否则人们的代码会被破坏。
  • @John 你确定标准要求6 在转换为FontFlags 时有效吗?我认为将未列出的值强制转换为枚举类是未定义的行为。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 2022-01-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
相关资源
最近更新 更多