2016-03-15 58 views
0

我有大量不受我控制的枚舉類型。模板化延遲初始化以內部模板化的typedef作爲參數的單例模式

enum ColorType { 
    RED, 
    GREEN, 
    BLUE }; 

我期待讓C++客戶端綁定他們希望枚舉類型的個體值雙向任何的std :: string(但獨特之處:例如(枚舉幾個數百1)辦法)。我得到這個使用升壓bimap的(V1.60)工作 - 忽略邊界檢查等在這裏:

template <typename L, typename R> boost::bimap<L, R> 
     makeBimap(std::initializer_list<typename boost::bimap<L, R>::value_type> list) 
     { 
      return boost::bimap<L, R>(list.begin(), list.end()); 
     }; 

template<typename E> class EnumWithString 
{ 
private: 
    typedef typename boost::bimap<E, std::string > BMEnumType; 
    const BMEnumType _biMap; 

    EnumWithString(const EnumWithString<E>&) = delete; 
    EnumWithString& operator=(const EnumWithString<E>&) = delete; 
public: 
    EnumWithString(const BMEnumType& biMap) : _biMap(biMap) {}; 
    const std::string& getString(const E& e) const { 
     return this->_biMap.left.at(e); 
    } 
    const E& getEnum(const std::string& s) const { 
     return this->_biMap.right.at(s); 
    } 
}; 

使得例如客戶端代碼(隨意想象可讀性類型定義):

EnumWithString<ColorType> stringBoundEnum(makeBimap<ColorType, std::string>({ { ColorType::RED, "Rouge" }, 
{ ColorType::BLUE, "Bleu" },                     
{ ColorType::GREEN, "Vert" } })); 
    cout << stringBoundEnum.getString(ColorType::GREEN) << endl; 
    cout << stringBoundEnum.getEnum("Bleu") << endl; 

這給出了正確的輸出。該粗糙的一點是,我需要這些創建映射(如stringBoundEnum)是單身,也就是我正在尋找類似的接口(再想象類型定義):

EnumWithStringSingleton<ColorType>::setInstance(makeBimap<ColorType, std::string>({ { ColorType::RED, "Rouge" }, 
                       { ColorType::BLUE, "Bleu" }, 
                       { ColorType::GREEN, "Vert" } })); // called only once by client 

cout << EnumWithStringSingleton<ColorType>::getInstance().getString(ColorType::GREEN) << endl; 

理想的情況下,我找的東西,用模板辛格爾頓工作採取單CTOR參數,如:

template <typename T, typename CTORArgument> class LazyInitSingleton 
{ 
public: 
    static T& getInstance(const CTORArgument& arg) 
    { 
     static T& theInstance(arg); 
     return theInstance; 
    }  
private: 
}; 

的問題是,我的情況下,CTORArgument是一個模板類中定義的模板化的typedef。我很想知道人們是如何解決這個問題的(SFINAE也許?)。

回答

1

簡單的解決辦法就是讓你的單身爲EnumWithString需要更具體:

template <typename EnumWithStringType> class LazyInitSingleton 
{ 
public: 
    // You have to make BMEnumType public 
    static EnumWithStringType& getInstance(const typename EnumWithStringType::BMEnumType& arg) 
    { 
     static EnumWithStringType theInstance(arg); 
     return theInstance; 
    } 
}; 

LazyInitSingleton<EnumWithStringType<ColorType>>::getInstance(...); 

甚至

template <typename EnumType> class LazyInitSingleton 
{ 
public: 
    static EnumWithString<EnumType>& getInstance(const EnumWithString<EnumType>::BMEnumType& arg) 
    { 
     static EnumWithString<EnumType> theInstance(arg); 
     return theInstance; 
    } 
}; 

LazyInitSingleton<ColorType>::getInstance(...); 
+0

是的,這個偉大的工程。我認爲我的想法太過於保持Singleton類的通用性,從而使結構過於複雜。爲了讓它編譯,我添加了typename,以便它識別'BMEnumType',但是正確的想法在那裏:typedef typename boost :: bimap BMEnumType;'和static EnumWithString &getInstance(const BMEnumType& arg)'簽名。謝謝! –

+0

@HansRoggeman沒問題,很高興幫助。 –