【问题标题】:C/C++: extract a subset of one enum to form a new enumC/C++:提取一个枚举的子集以形成一个新的枚举
【发布时间】:2019-05-24 04:43:10
【问题描述】:

假设我有一个列出所有人员的主枚举:

typedef enum all_personnel {
     // male
     TONY,
     MIKE,
     JIM,
     // female
     JESSICA,
     MARY,
} all_personnel_t;

现在我想为男性和女性定义另外两个枚举(例如,因为某些函数只接受男性或女性枚举参数),但我想使用与主枚举中相同的名称标识符。在 C/C++ 中可能吗?还是有其他方法?

似乎以下不起作用(编译器抱怨redeclaration of enumerator ‘TONY’等:

typedef enum male_personnel {
    TONY,
    MIKE,
    JIM,
} male_personnel_t;

【问题讨论】:

  • 你想用 C 还是 C++ 做这个?
  • 在 C 中,任何enum 类型中的枚举常量必须与范围内所有其他enum 类型中的所有其他枚举常量不同——除非您在函数内重新定义类型,这可能不是您想要做的。枚举常量在ordinary identifiers命名空间中,还有变量名、类型名、函数名等。

标签: c++ c enums


【解决方案1】:

here 所述,您可以在 C++ 中通过使用范围枚举 (C++11) 来执行此操作,如下所示

enum class all_personnel_t { TONY, MARY };
enum class male_personnel_t { TONY };

或者您可以将枚举放在命名空间中,如下所示

namespace all
{
    enum all_personnel_t { TONY, MARY };
}
namespace male
{
    enum male_personnel_t { TONY };
}

【讨论】:

    【解决方案2】:

    C

    这在 C 中是不可能的,因为范围内不同枚举的所有枚举常量都是同一个命名空间的一部分,称为普通标识符命名空间。所以对常量使用相同的名称会导致重新声明错误。

    按照 C11 标准:

    6.2.3 Name spaces of identifiers

    1. 因此,不同类别的标识符有单独的名称空间,如下所示:
      ...
      — 所有其他标识符,称为普通标识符(在普通声明符中声明或作为枚举常量)。

    C++

    如果您使用scoped enumerations,这在 C++ 中是可能的。

    enum class all_personnel {
         // male
         TONY,
         MIKE,
         JIM,
         // female
         JESSICA,
         MARY,
    } ;
    
    enum class male_personnel {
        TONY,
        MIKE,
        JIM,
    } ;
    

    但是,请注意,没有从作用域枚举器的值到整数类型或从一个作用域枚举器到另一个作用域枚举器的隐式转换。 这是因为每个枚举数都成为枚举类型的命名常量。

    所以下面是不可能的:

    male_personnel mp2 = all_personnel::TONY; //will not work
    all_personnel ap2 = male_personnel::MIKE; //will not work   
    

    这也不是:

    male_personnel mp1 = male_personnel::MIKE; 
    all_personnel ap1 = all_personnel::TONY; 
    mp1 = ap1; //will not work
    

    Demo

    【讨论】:

    • 感谢您的回答。除了没有隐式转换之外,似乎没有强制来自两个范围的 MIKE 具有相同的值,除非我在多个位置明确指定相同的值 MIKE=0,这是我想要避免的。我目前在 C 中的解决方法是在子集枚举标识符中添加下划线前缀,例如 _MIKE = MIKE。 “代价”是有时我用MIKE,有时我用_MIKE
    • @bruin:不客气。请注意,在 C 中,始终保留所有以下划线和大写字母或另一个下划线开头的标识符。因此,代码中的 _MIKE 之类的内容可能会导致未定义的行为。
    • 哎呀。我没有意识到这一点。感谢您指出这一点,我会将下划线更改为其他字符。
    猜你喜欢
    • 1970-01-01
    • 2016-11-30
    • 1970-01-01
    • 2010-12-22
    • 2010-09-11
    • 2010-11-26
    • 2011-02-17
    • 2021-01-04
    相关资源
    最近更新 更多