模板化的Lazy Initialization Singleton将内部模板化typedef作为参数

时间:2016-03-15 23:35:16

标签: c++ templates c++11 visual-c++ singleton

我有大量不同的枚举类型,我无法控制。例如(几百个枚举中的一个):

enum ColorType {
    RED,
    GREEN,
    BLUE };

我希望允许C ++客户端将他们希望的任何std :: string绑定到枚举类型的各个值(但是以双向方式唯一)。我使用boost 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);
    }
};

制作示例客户端代码(可以随意设想typedef的可读性):

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)是单例,即我正在寻找一个类似的界面(再次想象一下typedefs):

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;

理想情况下,我正在寻找适合模板化Singleton的东西,它采用一个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 个答案:

答案 0 :(得分:1)

简单的解决方案是让您的单身人士更具体地满足String nextElement = element.equals("Fire") ? "Metal" : (element.equals("Metal") ? "Water" : ...);

的需求
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(...);