enum class

C 风格枚举和 C++ 新增的 enum class:

enum { ITEM_A1, ITEM_A2 };
enum B { ITEM_B1, ITEM_B2 };
// 从 C 沿用来的语法:
// 1. 底层类型默认为int,但也能手动指定
// 2. 枚举名裸露在外
// 区别:
// C 允许前向声明 enum
// C++ 允许枚举列表为空;允许在表示类型时省略 enum 关键字;虽然枚举名裸露但也能通过限定名访问

// C++ 新增 enum class
enum C { ITEM_C1, ITEM_C2 };
// 类型不再裸露,需要使用限定名访问
// 没有默认底层类型,但是可以手动指定

C++ enum class 禁止了隐式转换,但是用来表示 id 还是不太方便:

#include <type_traits>

enum A: int { ITEM_1 };
enum { ITEM_2 };
enum class B: int { ITEM_3 };

// 即便底层类型相同,实际类型也不同
static_assert(! std::is_same_v<int, A>);
static_assert(sizeof(int) == sizeof(A));
static_assert(sizeof(int) == sizeof(ITEM_2));
// 枚举不是聚合类
static_assert(! std::is_aggregate_v<A>);
static_assert(! std::is_aggregate_v<B>);

int main() {
    [](int){}(ITEM_1);
    [](int){}(ITEM_2);
    
    int b3 = (int)B::ITEM_3;
    // [](int){}(B::ITEM_3); // no conversion from B to int
    // [](B){}(b3);          // no conversion from int to B
    [](B){}(B {b3});
    // [](B){}( {b3} );      // 即便是花括号也不能推导,因为枚举不是类

    // 强类型整数还是用 aggregate 做比较好:
    // 虽然整数到枚举可以使用构造的方式描述,但枚举到整数只能强制转换
    // 作为对比,aggregate 直接访问成员即可
}