【发布时间】:2018-08-22 20:31:22
【问题描述】:
阅读this answer 后,我尝试实现一些简单的 CRTP 用法。我想我会尝试实现单例(是的,我知道 - 它只是为了练习和研究)模式,因为链接的答案有点已经做到了......除了事实上它不能编译。
引用代码如下:
template <class ActualClass>
class Singleton
{
public:
static ActualClass& GetInstance()
{
if(p == nullptr)
p = new ActualClass;
return *p;
}
protected:
static ActualClass* p;
private:
Singleton(){}
Singleton(Singleton const &);
Singleton& operator = (Singleton const &);
};
template <class T>
T* Singleton<T>::p = nullptr;
class A: public Singleton<A>
{
//Rest of functionality for class A
};
然后我将其“现代化”为:
template <class T>
class Singleton {
public:
Singleton() = delete;
Singleton(const Singleton&) = delete;
Singleton(Singleton&&) = delete;
Singleton& operator = (const Singleton&) = delete;
Singleton& operator = (Singleton&&) = delete;
static T& get_instance() {
if(!instance)
instance = new T;
return *instance;
}
protected:
static inline T* instance = nullptr;
};
class A: public Singleton<A> {
//Rest of functionality for class A
};
然后我尝试创建对实例的引用:
auto& x = A::get_instance();
显然没有编译。
值得一提的是,我收到了非常相似的错误消息,特别是:
注意:'A::A()' 被隐式删除,因为默认定义格式错误:
class A : public Singleton<A>。
显然,代码的第二个sn-p无法编译,因为我们删除了默认构造函数并尝试在get_instance 方法中将其与new T 一起使用。
令我惊讶的是,第一个 sn-p 也无法编译,并带有类似的错误消息。链接的答案有错误吗?我将如何使用 CRTP 为单例实现 通用基类/接口?
【问题讨论】:
-
您是否考虑过不实现单例反模式并为自己省去很多麻烦?
-
@JesperJuhl,嗯,您是否考虑过阅读“是的,我知道 - 这只是为了实践和研究”部分?我无意在实际代码中使用它。此外,单例模式的用处不是这个问题的主题。我鼓励您阅读链接答案下方的第 6 条评论 - 获得 45 票的评论。
-
我仍然认为这是一个错误的练习题选择。