Принудительное создание статических членов в шаблонном классе

Я хочу использовать статический член в классе шаблона для создания экземпляра объекта-одиночки для каждого класса, который наследуется от этого класса шаблона.

Вот пример:

#include <iostream>
#include <vector>

struct X{

static std::vector<X*>& getRegistry(){
static std::vector<X*> registry;
return registry;
}

X(){
getRegistry().push_back(this); // Each X adds itself to the registry
}
};

template<typename T>
struct Y : X{
private:
static T instance; // The per-type singleton
};

template<typename T>
T Y<T>::instance {};

Идея состоит в том, что объекты типа X вводить себя в «реестр» всякий раз, когда они создаются. Учебный класс Y<T> что происходит от X является шаблоном класса, который должен создавать экземпляр статического одноэлементного объекта каждого типа, который наследуется от него (с использованием любопытно повторяющегося шаблона).

Идея состоит в том, что «реестр» будет содержать один объект каждого класса, который наследуется от Y<T>, Этим классам не нужно ничего делать, чтобы их добавили в реестр; вместо этого, просто наследуя от Y<T> должно быть достаточно для создания одноэлементного объекта, который добавляется в реестр.

Я попробовал свой код так:

struct A : Y<A>{};
struct B : Y<B>{};
struct C : Y<C>{};

int main(){
std::cout << "Number of objects in the registry: " << X::getRegistry().size() << std::endl;
// Should print "3"}

Скриптовая ссылка: http://ideone.com/aWDEg4

Желаемое поведение должно быть таким A, один B, и один C, должен быть в реестре. Но ни один из них не является. Проблема в том, что Y<T>::instance не создается ни для одного из классов, так как он не используется в коде. Тем не менее, я никогда не хочу использовать эти поля, они просто для создания экземпляра синглтона. Таким образом, существует ли способ вызвать создание экземпляра статического поля без необходимости добавления дополнительного кода к производным классам (т.е. A,B, а также C)?

Я знаю, что могу явно создать экземпляр template class Y<A>;, но это добавило бы дополнительный код к производному классу A,

0

Решение

Вы можете просто создать статические экземпляры:

struct A : Y<A>{};
struct B : Y<B>{};
struct C : Y<C>{};

static A a;
static B b;
static C c;

int main(){
std::cout << "Number of objects in the registry: " << X::getRegistry().size() << std::endl;
}

выход:

Number of objects in the registry: 3
1

Другие решения

Я не думаю, что вы можете избежать привлечения клиентов Y, но вы можете сделать Yчастный конструктор форсирование участие клиента. Например, это работает так, как вы хотите:

template<typename T>
struct Y : X {
Y(const Y<T> &other) {}
static Y<T> create() { &instance; return Y<T>(); }
private:
static T instance; // The per-type singleton
Y() {}
};

template<typename T>
T Y<T>::instance {};

struct A : Y<A> { A() : Y(Y::create()) {} };
struct B : Y<B> { B() : Y(Y::create()) {} };
struct C : Y<C> { C() : Y(Y::create()) {} };

Участие клиента является вызовом Y::create что также случается, чтобы заставить экземпляр instance член. Конечно, это, вероятно, не то, что вы хотели, но это работает. Обратите внимание, мой предыдущий комментарий о this Указатель будет по-прежнему применяться, даже если вы можете добавить статические экземпляры в свой реестр.

0

По вопросам рекламы [email protected]