我有一些任意的枚举,如下所示。
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 ++。
答案 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;
}