在C ++中使用CRTP的模板化单例策略

时间:2012-11-12 16:09:49

标签: c++ templates design-patterns singleton

有许多人声称他们的单例实现是健壮的和通用的,因为它使用元编程结构。

我的目标是在派生类上强制执行单例策略,这样我就不必显式(手动)将派生类的构造函数声明为私有。我认为通过使模板化的单例成为您派生的类的朋友,可以天真地将实例静态变量和getter添加为策略。但这并不优雅。

我从这段代码开始,除其他外,它是作为单身人士的正确(即完整)设计而给出的,而它显然允许多个实例:

template <class CWrappedClass>
class CSingleton
{
protected:
    static CWrappedClass* ms_instance;
private:
    CSingleton(){}
    CSingleton(const CSingleton& ) {}
    CSingleton& operator = (const CSingleton&) {}

public:
    static CWrappedClass& GetInstance()
    {
        if (ms_instance == NULL)
            ms_instance = new CWrappedClass;
        return *ms_instance;
    }
};

template <class CWrappedClass>
CWrappedClass* CSingleton<CWrappedClass>::ms_instance = NULL;

这个“政策”的单身客户端,使用CRTP:

class CThing : public CSingleton<CThing>
{
     // friend class CSingleton<CThing>; // only if ctor is private!
public:
    void DoNothing()
    {
        std::cout<<" Nothing \n";
    }
    CThing()
    {
        std::cout<<" single ";
    }
};

注意这不是CRTP Singleton政策的正确实施,它只是问题的一部分!

代码不会按原样编译。基本单例策略类将其构造函数声明为private,因此除非子类是此类的朋友,否则它不支持派生实例。人们通常会使构造函数受到保护,这意味着没有什么可以阻止用户使派生类非单一的。

问题/问题:是否有任何机制可以强制实施单例策略而无需手动将派生类的构造函数设为私有?

1 个答案:

答案 0 :(得分:2)

如果您确实希望使用此模式:

  1. 模板的构造函数应该受到保护,而不是私有,以便派生类可以访问它。否则它自己的构造函数不能构造基类。

  2. 派生类可以使模板(它的基类)成为朋友并拥有私有构造函数。

  3. 或者,有一个实现的宏实际上是从其编译单元中的派生类构造实例。当我使用类似的模型时(通过强制,修复使用单例的代码并且我没有改变它,只有实现单例的实现方式),我选择了这个选项,实际上经历了boost::once在.cpp文件中构造。