2013-06-28 41 views
1

背景有效使用constexpr的

我想要實現:我想實現像一個Java枚舉(即枚舉,有一些額外的功能。) 。我想出了一個使用兩個類的解決方案,其中一個類表示一個值,另一個表示使用靜態變量來表示每個值的可能值的枚舉。我希望它是一個真正的枚舉替代,包括在模板實例化中使用枚舉值的可能性。爲此,枚舉值需要是一個常量表達式(constexpr)。但是,我不確定是否正確使用了constexpr。是與非const成員

守則

這裏是我想出了代碼:

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代替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();*/ 
} 

這個工程,我所期望的 - 我可以代替模板中使用的值從EnumTypeListEnumType::Enum實例如上所示,但我不能EnumType x = EnumTypeList::C;

的問題

當代碼編譯正確,而不在gcc和鐺任何警告做到這一點,我不知道我是否正確地使用constexpr。問題是,儘管EnumType構造函數和轉換運算符operator Enum()是constexpr,但它們都訪問變量m_IDm_foo,這些變量不是常量(因爲我需要賦值運算符)。

回答

3

這很好,字面類型的成員可以修改。

爲了在常量表達式中使用該類型,您必須使用常量參數來構造它,但那樣做是可以的,因爲您這樣做;

static constexpr EnumType A = EnumType(EnumType::val_A, 5); 

構造的目的是有效的常量表達式所以可以用於初始化constexpr可變A。你不修改對象的成員,所以它們可以修改並不重要。

Clang特別對常量表達式非常嚴格,如果你做錯了,會給出錯誤。

該對象可用於在需要的常量表達式:

constexpr EnumType A5(EnumType::val_A, 5); 

例如

constexpr int i = A5.getFoo(); 

該對象不能:

EnumType A6(EnumType::val_A, 6); 
constexpr int i = A6.getFoo(); // error