为每个枚举器添加代码

Adding code for each enumerator

本文关键字:添加 代码 枚举      更新时间:2023-10-16

我有一些任意枚举,如下所示。

enum MyEnumWith2Items {
    Item1,
    Item2
};
enum MyEnumWith3Items {
    Item1,
    Item2,
    Item3
};

我想添加一些依赖于每个枚举器的代码。例如,在与每个项目对应的类中添加一个字段。

template<typename EnumType>
struct MyStruct {
    /* magic */
};
MyStruct<MyEnumWith2Items> a; // a has the fields i1 and i2, but not i3
MyStruct<MyEnumWith3Items> b; // b has i1, i2 and i3

这可能吗?
enum class怎么样?
使用static字段或方法或任何类型的代码怎么样?

类定义可以采用任何形式,我的例子只是一个例子。
我可以使用任何版本的C++。

如果您对 myStruct 的静态成员感兴趣,请使用 C++14(因此静态模板成员可用(,您可以定义myStruct如下

template <typename E>
struct myStruct
 {
   template <E I>
   struct wrp
    { int value; };
   template <E I>
   static wrp<I> item;
 };
template <typename E>
template <E I>
myStruct<E>::wrp<I> myStruct<E>::item { 0 };

并给出以下枚举器

enum MyEnumWith2Items { Item1, Item2 };
enum MyEnumWith3Items { Item3, Item4, Item5 };

你可以写

int main ()
 {    
   myStruct<MyEnumWith2Items>::item<Item1>.value = 1;
   myStruct<MyEnumWith2Items>::item<Item2>.value = 2;
   myStruct<MyEnumWith3Items>::item<Item3>.value = 3;
   myStruct<MyEnumWith3Items>::item<Item4>.value = 4;
   myStruct<MyEnumWith3Items>::item<Item5>.value = 5;
 }

在 C++14 之前(在 C++14 本身中(,您可以使用模板方法中的静态变量获得类似的结果;下面是一个完整示例

#include <iostream>
enum MyEnumWith2Items { Item1, Item2 };
enum MyEnumWith3Items { Item3, Item4, Item5 };
template <typename E>
struct myStruct
 {
   template <E I>
   int & item ()
    { static int value = 0; return value; }
 };
int main ()
 {
   myStruct<MyEnumWith2Items>  e2;
   myStruct<MyEnumWith3Items>  e3;
   e2.item<Item1>() = 1;
   e2.item<Item2>() = 2;
   e3.item<Item3>() = 3;
   e3.item<Item4>() = 4;
   e3.item<Item5>() = 5;
   std::cout << "e2: " << e2.item<Item1>() << ", " << e2.item<Item2>() 
      << std::endl;                              // print e2: 1, 2
   std::cout << "e3: " << e3.item<Item3>() << ", " << e3.item<Item4>() 
      << ", " << e3.item<Item5>() << std::endl;  // print e3: 3, 4, 5
 }

我的第一个想法是做这种事情,但有一个警告。

enum class Enum1 {a, b, size};
enum class Enum2 {c, d, e, size};
template<typename E>
struct S
{
    char field[size_t(E::size)];  
};
int main()
{
    S<Enum1> s1;
    S<Enum2> s2;
    std::cout << sizeof(s1.field) << std::endl << sizeof(s2.field) << endl;
    // 2 and 3
}

当然需要注意的是,enum s 必须为 [0, n( 才能使最终的size技巧起作用

这可能看起来有点多余,但如果需要,它确实允许多态类型。我已将不同的枚举类型包装到一组从基类型类继承的类中。然后我使用了具有专用化的模板结构。我还添加了通过模板参数列表或公开分配类设置值的功能。现在,这只是为了处理实际的枚举值;但是,您可以轻松地添加此内容以添加每种类型的字段。

#include <iostream>
class Root {
public:
    enum Type {
        TYPE_1 = 1,
        TYPE_2,
        TYPE_3
    };
protected:
    Type type_;
public:
    explicit Root(Type type) : type_(type) {}
    virtual ~Root() {}
    Type getType() const {
        return type_;
    }
};
class Derived1 : public Root {
public:
    enum TwoItems {
        ITEM_1 = 1,
        ITEM_2
    } item_;
    Derived1() : Root(TYPE_1) {}
    explicit Derived1(unsigned itemValue) : 
        Root(TYPE_1), item_(static_cast<Derived1::TwoItems>(itemValue) ) {}
};
class Derived2 : public Root {
public:
    enum ThreeItems {
        ITEM_3 = 3,
        ITEM_4,
        ITEM_5
    } item_;
    Derived2() : Root(TYPE_2) {}
    explicit Derived2(unsigned itemValue) :
        Root(TYPE_2), item_(static_cast<Derived2::ThreeItems>(itemValue)) {}
};
class Derived3  : public Root {
public:
    enum FourItems {
        ITEM_6 = 6,
        ITEM_7,
        ITEM_8,
        ITEM_9
    } item_;
    Derived3() : Root(TYPE_3) {}
    explicit Derived3(unsigned itemValue) :
        Root(TYPE_3), item_(static_cast<Derived3::FourItems>(itemValue)) {}
};
template<typename ClassType, unsigned itemValue = 0>
struct MyStruct {
    ClassType derived_;
};
template<unsigned itemValue>
struct MyStruct<Derived1, itemValue> {
    Derived1 derived_{ itemValue };
};
template<unsigned itemValue>
struct MyStruct<Derived2, itemValue> {  
    Derived2 derived_{ itemValue };
};
template<unsigned itemValue>
struct MyStruct<Derived3, itemValue> {  
    Derived3 derived_{ itemValue };
};
int main() {
    MyStruct<Derived1, 2> structA;
    MyStruct<Derived2, 4> structB;
    MyStruct<Derived3, 8> structC;
    std::cout << structA.derived_.item_ << std::endl;
    std::cout << structB.derived_.item_ << std::endl;
    std::cout << structC.derived_.item_ << std::endl;
    std::cout << std::endl;
    structA.derived_.item_ = static_cast<Derived1::TwoItems>(1);
    structB.derived_.item_ = static_cast<Derived2::ThreeItems>(5);
    structC.derived_.item_ = static_cast<Derived3::FourItems>(9);
    std::cout << structA.derived_.item_ << std::endl;
    std::cout << structB.derived_.item_ << std::endl;
    std::cout << structC.derived_.item_ << std::endl;
    std::cout << std::endl;

    // Also
    MyStruct<Derived1> structA2;
    MyStruct<Derived2> structB2;
    MyStruct<Derived3> structC2;
    structA2.derived_.item_ = static_cast<Derived1::TwoItems>(1);
    structB2.derived_.item_ = static_cast<Derived2::ThreeItems>(3);
    structC2.derived_.item_ = static_cast<Derived3::FourItems>(7);
    std::cout << structA2.derived_.item_ << std::endl;
    std::cout << structB2.derived_.item_ << std::endl;
    std::cout << structC2.derived_.item_ << std::endl;
    char c;
    std::cout << "nPress any key to quit.n";
    std::cin >> c;
    return 0;
}