【问题标题】:Is there a way to nest enums in c++ without namespace?有没有办法在没有命名空间的 c++ 中嵌套枚举?
【发布时间】:2020-03-15 01:05:41
【问题描述】:

我正在为给定的 AST 实现一个字节码生成器。在创建表达式类时,我注意到一元和二元运算符之间的区别。为简单起见,unum 是首选解决方案,所以我以这种方式嵌套了 enun:

enum EXP_TYPE
{
    enum BINARY
    {
        PLUS,
        MINUS,
        MULTIPLY,
        DIV,
        ...
    };
    enum UNARY
    {
        PLUS,
        MINUS,
        POINTER,
        INC,
        ...
    };
};

当然,此代码会引发警告,告知这是不允许的。所以我在stackoverflow和其他来源上搜索了一下,找到了使用namespace而不是enum进行EXP_TYPE声明的解决方案。但是现在的问题是表达式类内部的使用:

class expression
{
    expression *right_exp;
    expression *left_exp;
    EXP_TYPE type;
    ...
};

不再允许使用 EXP_TYPE,因为它是 namespace 而不是 enum 类型。我打算做的是一个通用的enum 声明,它可以用作类内部的属性,在这里通用意味着它可以是BINARYUNARY,即也就是说,EXP_TYPE type 属性可以有如下赋值和比较:

 expression exp1;
 exp1.type = EXP_TYPE::BINARY::PLUS;
 exp1.type = EXP_TYPE::UNARY::PLUS;

有没有一种方法可以在不使用namespace 的情况下制作这些简单的泛型类型,或者不需要为一元和二元运算符创建类层次结构?

【问题讨论】:

  • 不,没有。
  • 枚举不是这样工作的。枚举是一种引入符号整数常量的方法,按顺序编号。因此,例如enum EXP_TYPE { BINARY_PLUS, UNARY_PLUS} 然后BINARY_PLUS 等于0UNARY_PLUS 等于1。使用嵌套枚举,PLUS 有什么价值? BINARY::PLUSUNARY::PLUS 有何不同?
  • @Someprogrammerdude 我可以想象BINARY::DIV == UNARY_PLUS-1 (ish),如果我们有一个假设的枚举子范围。但我们没有。而且,公平地说,我们也不需要它们。

标签: c++ enums namespaces compiler-construction code-generation


【解决方案1】:

不,您不能在枚举内创建范围。

相反,请使用较长的名称(例如 EXP_TYPE::BINARY_PLUS)对您的枚举进行分类。

【讨论】:

    【解决方案2】:

    我把这个当作谜题,想知道我可以多接近 OP 的要求。

    这就是我得到的(虽然我必须承认它看起来有点吓人):

    #include <cassert>
    #include <iostream>
    
    struct ExpType {
      struct Unary {
        enum {
          Plus, Minus, Pointer, Inc,
          N
        };
      };
      struct Binary {
        enum {
          Plus = Unary::N, Minus, Multiply, Div,
          N
        };
      };
      enum {
        N = Binary::N
      };
    
      int value;
    
      ExpType(int value = 0): value((assert(value >= 0 && value < N), value)) { }
      ~ExpType() = default;
      ExpType(const ExpType&) = default;
      ExpType& operator=(const ExpType&) = default;
    
      operator int () { return value; }
    };
    
    int main()
    {
      for (int i = 0; i < ExpType::N; ++i) {
        ExpType expType = i;
        switch (expType) {
    #define CASE(TYPE) case TYPE: std::cout << #TYPE "\n"; break
          CASE(ExpType::Unary::Plus);
          CASE(ExpType::Unary::Minus);
          CASE(ExpType::Unary::Pointer);
          CASE(ExpType::Unary::Inc);
          CASE(ExpType::Binary::Plus);
          CASE(ExpType::Binary::Minus);
          CASE(ExpType::Binary::Multiply);
          CASE(ExpType::Binary::Div);
    #undef CASE
          default: std::cout << "Unknown expression type!\n";
        }
      }
    }
    

    输出:

    ExpType::Unary::Plus
    ExpType::Unary::Minus
    ExpType::Unary::Pointer
    ExpType::Unary::Inc
    ExpType::Binary::Plus
    ExpType::Binary::Minus
    ExpType::Binary::Multiply
    ExpType::Binary::Div
    

    Live Demo on coliru

    但是,我必须承认,我个人肯定更喜欢other answer 中推荐的内容。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-10-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-15
      • 1970-01-01
      • 1970-01-01
      • 2023-03-05
      相关资源
      最近更新 更多