背景
我想要实现的目标:我正在尝试实现类似 Java 枚举的东西(即具有一些附加功能的枚举)。我提出了一个使用两个类的解决方案,其中一个类表示一个值,另一个类作为可能值的枚举,使用静态变量来表示每个值。我希望它成为枚举的真正替代品,包括在模板实例化中使用枚举值的可能性。为此,枚举值需要是一个常量表达式 (constexpr)。但是,我不确定我是否正确使用了 constexpr。
编码
这是我想出的代码:
class EnumType {
public:
enum Enum {val_A, val_B, val_C};
friend class EnumTypeList;
EnumType()
: m_ID(val_A), m_foo(0) {}
constexpr operator Enum() const {return m_ID;};
constexpr unsigned int getFoo() const {return m_foo;};
protected:
constexpr EnumType(const Enum v, const int foo)
: m_ID(v), m_foo(foo) {}
private:
Enum m_ID;
int m_foo;
};
class EnumTypeList {
public:
static constexpr EnumType A = EnumType(EnumType::val_A, 5);
static constexpr EnumType B = EnumType(EnumType::val_B, 4);
static constexpr EnumType C = EnumType(EnumType::val_C, 8);
};
该类EnumType
保存每个值的信息并提供一些附加函数(这里它存储可以使用getFoo()
函数访问的附加值 m_foo)。枚举本身由EnumTypeList
包含静态 constexpr 变量的 表示,其中每个变量表示枚举的一个可能值。这段代码允许我在模板中使用变量来EnumTypeList
代替EnumType::Enum.
Even 在下面的代码中:
template <EnumType::Enum T>
class Test {
public:
void test() {
std::cout << "Enum is not A" << std::endl;
}
};
template <>
class Test<EnumType::val_A> {
public:
void test() {
std::cout << "Enum is A" << std::endl;
}
};
int main() {
Test<EnumTypeList::A> a;
a.test();
Test<EnumTypeList::B> b;
b.test();
// this shouldn't compile
/*EnumType x = EnumTypeList::C;
Test<x> c;
c.test();*/
}
这正如我所期望的那样工作——我可以使用 from 的值EnumTypeList
代替EnumType::Enum
模板实例化,如上所示,但我不能这样做EnumType x = EnumTypeList::C;
问题
虽然代码在 gcc 和 clang 下正确编译而没有任何警告,但我不确定我是否正确使用了 constexpr。问题是,虽然EnumType
构造函数和转换运算符operator Enum()
是 constexpr,但它们都访问变量m_ID
并且m_foo
不是常量(因为我需要赋值运算符)。