c++ - 在使用 Clang 编译 CRTP Singleton 时,如何解决声称缺少 "explicit instantiation declaration"的问题?

标签 c++ c++11 singleton clang++ crtp

我们正在使用 curiously recurring template pattern实现单例。但是,在最近的 Clang 版本中,我们收到了 -Wundefined-var-template 警告。建议的修复方法是添加“显式实例化声明”。

我试图这样做,但后来在定义单例模板类成员变量的编译单元中出现有关“实例化后的显式特化”的错误。

解决此警告突出显示的问题的适当构造是什么?


简化详细信息(已删除大部分逻辑,以制作 MCVE):

单例基础.hh:

template < class T > class SingletonBase {
public:
  static T * get_instance() {
    if ( ! instance_ ) {
      instance_ = T::create_singleton_instance();
    }
    return instance_;
  }
private:
  static T * instance_;
};

单例.hh:

#include "SingletonBase.hh"

class Singleton : public SingletonBase< Singleton > {
  friend class SingletonBase< Singleton >;
public:
  int do_stuff(int v) { return v+2; }
private:
  static Singleton * create_singleton_instance() {
    return new Singleton;
  }
};

单例.cc:

#include "Singleton.hh"
template <> Singleton * SingletonBase< Singleton >::instance_( nullptr );

当我们使用最新版本的 clang(3.9.0;但不是 clang 3.7)进行编译时,在编译 Singleton.cc 以外的文件时会收到警告。 (使用 -std=c++11 和 -Werror)

In file included from OtherFile.cc:2:
In file included from ./Singleton.hh:2:
./SingletonBase.hh:5:16: warning: instantiation of variable 'SingletonBase<Singleton>::instance_' required here, but no definition is available [-Wundefined-var-template]
        if ( ! instance_ ) {
               ^
OtherFile.cc:5:25: note: in instantiation of member function 'SingletonBase<Singleton>::get_instance' requested here
      return Singleton::get_instance()->do_stuff(4);
                        ^
./SingletonBase.hh:11:18: note: forward declaration of template entity  is here
       static T * instance_;
             ^

./SingletonBase.hh:5:16: note: add an explicit instantiation declaration to suppress this warning if 'SingletonBase<Singleton>::instance_' is explicitly instantiated in another translation unit
        if ( ! instance_ ) {
               ^
1 error generated.

我在 Singleton.hh 的末尾添加了以下行,因为这就是我的 lead to believe显式实例化声明语法应该是。

extern template Singleton* SingletonBase< class Singleton >::instance_;

虽然这修复了编译 OtherFile.cc 的问题,但在编译 Singleton.cc 时会导致新的错误

Singleton.cc:3:57: error: explicit specialization of 'instance_' after instantiation
    template <> Singleton * SingletonBase< Singleton >::instance_( nullptr );
                                                    ^
./Singleton.hh:14:66: note: explicit instantiation first required here
    extern template Singleton* SingletonBase< class Singleton >::instance_;
                                                             ^
1 error generated.

我应该在这里做什么来修复这些警告/错误?对于我不理解的显式实例化声明,是否有更合适的语法?

最佳答案

最简单的解决方法是在 SingletonBase.hh 中定义 instance_:

template < class T > class SingletonBase {
public:
  static T * get_instance() {
    if ( ! instance_ ) {
      instance_ = T::create_singleton_instance();
    }
    return instance_;
  }
private:
  static T * instance_;
};

template <typename T>
T* SingletonBase<T>::instance_ = nullptr;

但是,如果您要依赖 T::create_singleton_instance() 来创建实例,我看不到 SingletonBase 的意义。您不妨在派生类中实现 get_instance()

只有当基类可以使用默认构造函数构造派生类的实例时,使用 CRTP 实现单例模式才有意义。

template < class T > class SingletonBase {
   public:
      static T& get_instance() {
         static T instance_;
         return instance_;
      }
   private:
};

进一步阅读:How to implement multithread safe singleton in C++11 without using <mutex>

关于c++ - 在使用 Clang 编译 CRTP Singleton 时,如何解决声称缺少 "explicit instantiation declaration"的问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39420569/

相关文章:

c++ - 我必须以 [ios::binary] 模式打开文件才能获取其大小吗?

c++ - 64 位 C++ 二进制文件消耗大量内存,即使二进制文件很大

c++ - MongoDB C++ 驱动程序 3.0 以字符串形式获取文档并避免使用 json

c++ - 为什么 uniform_int_distribution<uintmax_t> 适用于 62 位数字但不适用于 63 或 64 位数字?

c++ - 在gcc或clang中调试SFINAE

c - C 中的单例模式

c++ - 变体与继承

c++ - 打包类+继承的内存布局

java - 在 Java 中实现单例模式

c++ - boost 单例