2013-06-27 27 views
4

首先,我想要一個普通的枚舉而不是基於位的枚舉,因爲不同枚舉的數量將超出任何整數類型。我也想利用C++ 11 enum class的類型安全性。要做到這一點,自然選擇將是std::bitset,但我不知道如何將這兩者結合在一起。使用枚舉類與std :: bitset

將需要一個自定義bitset?如何繞過這樣的課程的實施?

+0

我有點不確定你」再問一次你有沒有機會添加一些關於你想要做什麼的細節,或者可能是一個例子? –

+0

從我得到的結果來看,您希望通過枚舉類型安全地(不帶enum-to-int)標誌訪問''std :: bitset ''而不是類似類型。我的理解是否正確?確切地說, – milleniumbug

+0

。基本上我有現有的'enum class'定義,我想把它們打包成一個類型安全的'bitset'。 –

回答

8

因爲enum class es是enums的包裝,所以可以將它們轉換爲基礎類型。 並且使用一些私有繼承,您可以選擇性地從C++ stdlib類中導入一些功能,而不用擔心Liskov的原理。 成分產生更清晰的代碼。使用這些功能,我們可以包裝std::bitset。以下代碼僅包含功能組的子集,但可以進一步擴展。

最大值有問題 - 您無法獲得最大值enum class(或者我錯了嗎?)。所以我加了EnumTraits。現在用戶需要專門使用EnumTraits,常量值max等於enum的最大值,然後才能使用類。

#include <bitset> 
#include <type_traits> 

template<typename T> 
struct EnumTraits; 

template<typename T> 
class EnumClassBitset 
{ 
private: 
    std::bitset<static_cast<typename std::underlying_type<T>::type>(EnumTraits<T>::max)> c; 

    typename std::underlying_type<T>::type get_value(T v) const 
    { 
     return static_cast<typename std::underlying_type<T>::type>(v); 
    } 

public: 
    EnumClassBitset() : c() 
    { 

    } 

    bool test(T pos) const 
    { 
     return c.test(get_value(pos)); 
    } 

    EnumClassBitset& reset(T pos) 
    { 
     c.reset(get_value(pos)); 
     return *this; 
    } 

    EnumClassBitset& flip(T pos) 
    { 
     c.flip(get_value(pos)); 
     return *this; 
    } 
}; 

enum class BitFlags 
{ 
    False, 
    True, 
    FileNotFound, 
    Write, 
    Read, 
    MaxVal 
}; 

template<> 
struct EnumTraits<BitFlags> 
{ 
    static const BitFlags max = BitFlags::MaxVal; 
}; 

#include <iostream> 

int main() 
{ 
    EnumClassBitset<BitFlags> f; 
    f.flip(BitFlags::True); 
    f.flip(BitFlags::FileNotFound); 
    //f.flip(2); //fails to compile 
    std::cout << "Is False? " << f.test(BitFlags::False) << "\n"; 
    std::cout << "Is True? " << f.test(BitFlags::True) << "\n"; 
    std::cout << "Is FileNotFound? " << f.test(BitFlags::FileNotFound) << "\n"; 
    std::cout << "Is Write? " << f.test(BitFlags::Write) << "\n"; 
    std::cout << "Is Read? " << f.test(BitFlags::Read) << "\n"; 
} 

由於enum都不具備的許多功能很遺憾,並且更重要的是,C++ 11 enum class ES沒有改善的情況下,some programmers use static map wrapped in a class. Definitely a good read.

+0

嗯,這應該可以做成一個通用的模板,對嗎? –

+0

@KornelKisielewicz是的,這段代碼可以很容易地模板化。只是沒有直接寫模板,因爲我對他們不太滿意:)。 – milleniumbug

+0

好吧,我看到一個潛在的問題 - 有沒有簡單的方法來找到枚舉的最大值(不訴諸增加另一個枚舉值)...所以它可能必須是模板的第二個參數,太安全了:/。 –