Я использую любопытный шаблон повторяющегося шаблона (CRTP) для обеспечения функциональности, которая требует создания статических функций для базового класса. Часто я забываю явно создать экземпляры функций, и это приводит к неправильному поведению (функции не создаются). Ниже показан простой пример одноэлементного базового класса.
#include <iostream>
template <class T>
class Singleton {
public:
static const T& InstanceGet() {
if (!pInstance) { pInstance = new T; }
return *pInstance;
}
static int InstanceDestroy() __attribute__((destructor));
protected:
Singleton() = default;
Singleton(Singleton const &) = delete;
Singleton& operator=(Singleton const &) = delete;
private:
static T* pInstance;
};
template <class T>
int Singleton<T>::InstanceDestroy() {
if (pInstance) {
delete pInstance;
pInstance = nullptr;
}
return 0;
}
template <class T>
T* Singleton<T>::pInstance = nullptr;
class Test : public Singleton<Test> {
friend class Singleton<Test>;
};
// Explicit instantiate destructor (otherwise not called)
// template int Singleton<Test>::InstanceDestroy();
int main(int argc, char* argv[]) {
const Test& pTest = Test::InstanceGet();
return 0;
}
Если я забуду явно создать экземпляр int Singleton<Test>::InstanceDestroy(), функция не будет сгенерирована и вызвана при выгрузке библиотеки. Вопрос: Есть ли автоматический способ обеспечить создание таких функций?
Я нашел способ, но при запуске появляется фиктивный вызов. Добавьте следующую константу к базовому классу
const int atexit = Singleton<T>::InstanceDestroy();
что не очень элегантно.
Наконец, я должен упомянуть, что вопрос не в том, как обрабатывать синглтоны. Я использую вышеприведенный шаблон для создания издателей и подписчиков объектов, сбора мусора и т. д.
заранее спасибо
Вам действительно нужно сбросить синглтон? Синглтон Эльзы Мейерс лучше.
Я стараюсь избегать одиночек Мейерса. Мы используем старый компилятор, который не генерирует потокобезопасный код с использованием синглтона Мейерса (пример не является потокобезопасным). Кроме того, я хотел бы избежать вмешательства в работу многих синглтонов, зарегистрированных в огромном статическом приложении.
@SamVarshavchik Не вариант. Я бы хотел избежать статических переменных, которые автоматически вставляются в и без того бесконечный длинный список указателей на функции. __attribute__((destructor)) - это не взлом - это правильный способ зарегистрировать функцию для вызова перед выгрузкой
@SamVarshavchik Статический экземпляр класса не привел бы к вставке указателя функции на деструктор в список, где многие другие функции зарегистрированы с помощью atexit, то есть выход из приложения, а не выгрузка библиотеки





Вместо взлома
__attribute__((destructor))я бы попытался объявить внутренний класс с помощью деструктора разнообразия садов, а затем создать экземпляр статического класса внутреннего класса.