バックグラウンド
私が達成しようとしていること: Java列挙型(つまり、いくつかの追加機能を持つ列挙型)のようなものを実装しようとしています。1 つのクラスが値を表し、もう 1 つのクラスが静的変数を使用して各値を表す可能な値の列挙として機能する、2 つのクラスを使用するソリューションを思いつきました。テンプレートのインスタンス化で列挙型の値を使用する可能性を含め、列挙型の実際の代替品にしたいと考えています。これが機能するには、列挙値が定数式 (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
は各値の情報を保持し、いくつかの追加機能を提供します (ここでは、関数を使用してアクセスできる追加の値 m_foo を格納していgetFoo()
ます)。列挙自体は、静的な constexpr 変数を含む によって表されEnumTypeList
ます。ここで、各変数は列挙の可能な値を表します。このコードでは、次のコードのように、テンプレートEnumTypeList
で Even の代わりに変数を使用できます。EnumType::Enum.
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();*/
}
これは期待どおりに機能します。上記のようにテンプレートのインスタンス化EnumTypeList
の代わりに値を使用できますが、それを使用するEnumType::Enum
ことはできませんEnumType x = EnumTypeList::C;
問題
コードは gcc と clang で警告なしに正しくコンパイルされますが、constexpr を正しく使用しているかどうかはわかりません。問題は、EnumType
コンストラクターと変換演算子operator Enum()
は constexpr ですが、どちらも変数m_ID
にアクセスしm_foo
、定数ではないということです (代入演算子が必要なため)。