Мы используем любопытно повторяющийся шаблон шаблона для реализации синглтонов. . Однако в последних версиях Clang мы получаем предупреждение -Wundefined-var-template. Предлагаемое исправление заключается в добавлении «явного объявления создания экземпляра».
Я попытался сделать это, но затем получаю ошибки о «явной специализации после создания экземпляра» в модуле компиляции, где указано определение переменной-члена класса одноэлементного шаблона.
Какая подходящая конструкция для устранения проблемы, отмеченной этим предупреждением?
Упрощенные детали (большая часть логики была удалена для создания MCVE):
SingletonBase.hh:
template < class T > class SingletonBase {
public:
static T * get_instance() {
if ( ! instance_ ) {
instance_ = T::create_singleton_instance();
}
return instance_;
}
private:
static T * instance_;
};
Синглтон.хх:
#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;
}
};
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, так как это то, к чему я приводит полагаю, явный синтаксис объявления экземпляра должен быть.
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.
Что мне здесь делать, чтобы исправить эти предупреждения / ошибки? Есть ли более подходящий синтаксис для явного объявления экземпляра, который я не понимаю?
get_instance()
, сэкономить if, сделать его потокобезопасным. Ваш базовый класс не гарантирует, что это синглтон, но для него требуется функция create_instance. Я могу в любой момент создать два экземпляра Singleton, даже не касаясь вашего интерфейса. Вы не можете разрушить-воссоздать его. Вы можете иметь базовые и дочерние синглтоны одновременно. Вы протекаете и никогда не вызываете деструктор. Исправление? Удалите эти источники и начните заново. (Без обид, мы поможем вам выбрать подходящий) - person lorro   schedule 10.09.2016