为每个枚举器添加代码

时间:2017-06-18 17:18:48

标签: c++ templates enums

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

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 ++。

3 个答案:

答案 0 :(得分:4)

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

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 };

Pre C ++ 14(以及C ++ 14本身),你可以在模板方法中使用静态变量获得类似的结果;以下是一个完整的例子

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;
 }

答案 1 :(得分:3)

我的第一个想法是做这种事,但有一点需要注意。

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技巧发挥作用

答案 2 :(得分:0)

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

#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;
}