【问题标题】:Can an enumerator be defined in terms of other enumerators within the same enum type?可以根据同一枚举类型中的其他枚举数来定义枚举数吗?
【发布时间】:2014-09-16 09:02:04
【问题描述】:

出于好奇,我正在试验这个:

enum RxqType
{
    A = (1 << 0),
    B = (1 << 1),
    C = (A | B),
    D = A+B+C
};

枚举器 C 和 D 是根据早期的枚举器定义的。这是不寻常的,所以我不确定它是否安全。我无法通过 Google 找到有关它的示例(尽管可能会忽略)。

当我在 Visual C++ 2013 和 MinGW 上 printfcout CD 时似乎没问题。但我担心它是否符合标准,以及它是否会触发未定义的行为。

谁能回答我对标准一致性和未定义行为的担忧?还有什么我需要担心的吗?

【问题讨论】:

  • 来自 C++ 标准的示例:enum { d, e, f=e+2 };...
  • @PiotrNycz 哦,我应该记得在下一个问题之前查看标准。
  • @PiotrNycz 严格来说,示例并不规范。尽管该标准当然不太可能包含不合规的示例。
  • @Lundin,“符合标准”和“一个好主意”不一定是一回事。 ;)(没有评论这种语法是好还是坏,只是库代码并不总是用最佳实践编写的。)

标签: c++ c enums


【解决方案1】:
enum RxqType
{
    A = (1 << 0),
    B = (1 << 1),
    C = (A | B),
    D = A+B+C
};

在 C 和 C++ 中这是有效的。

对于 C:

(C11, 6.2.1p7) “每个枚举常量的作用域都在其定义的枚举数出现在枚举数列表中之后开始。”

对于 C++:

(C++11, 3.3.2p4) "枚举器的声明点紧跟在其枚举器定义之后。"

【讨论】:

    【解决方案2】:

    是的,这在 C99 标准草案 6.2.1Scopes of identifiers 中有介绍,它告诉我们每个枚举数在定义后都在范围内:

    每个枚举常量的作用域 在其定义的枚举数出现在枚举数列表中之后开始。

    这在草案 C++ 标准部分 3.3.2 声明点中有所涉及:

    声明点 枚举紧随其枚举说明符(7.2)或其第一个标识符(如果有)之后 opaque-enum-declaration (7.2),以先到者为准。

    为了完整起见,我们可以转到 C99 标准草案的 6.7.2.2 枚举说明符部分,它告诉我们可以通过常量表达式设置枚举器,而枚举器本身就是一个常量表达式.

    enumerator:
        enumeration-constant
        enumeration-constant = constant-expression
    

    什么是常量表达式在6.6 部分介绍常量表达式,它告诉我们枚举数是常量,整数常量的算术表达式也是常量表达式。

    【讨论】:

      【解决方案3】:

      尽管如前所述,它是完全有效的,但您必须注意一件事:在定义枚举类型时,在 C++ 中,已声明的枚举数可能不具有您期望的确切类型.结果,像

      enum E {
        a = INT_MAX,
        b = UINT_MAX,
        c = a + 1, // error: overflow
      };
      

      无效,即使这是:

      enum E {
        a = INT_MAX,
        b = UINT_MAX,
      };
      enum E2 {
        c = a + 1, // okay: a is promoted to unsigned int
      };
      

      对于类似的示例,重载决议的行为可能与您预期的不同:

      char f(int);
      template <typename T>
      char (&f(T))[2];
      
      enum E {
        a = 0,
        b = sizeof(f(a)), // 1
      };
      enum E2 {
        c = sizeof(f(a)), // 2
      };
      

      还有其他类似的例子有点不直观。

      对于 C,规则要简单一些。在 C 中,枚举常量的类型与枚举类型无关,所以我的a + 1 示例即使使用E2 也是无效的。这确实会带来一致的结果。

      【讨论】:

        【解决方案4】:

        是的,100% 有效。这很好,事实上,值得赞赏。

        enum RxqType
        {
            A = (1 << 0),
            B = (1 << 1),
            C = (A | B),
            D = A+B+C
        };
        

        【讨论】:

        • “谁能回答我对标准一致性和未定义行为的担忧?”
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多