Как мне инициализировать эту переменную статического класса в моем классе шаблона?

У меня есть следующий код (на ideone.com):

template<class T>
class CMemoryPool
{
public:
    CMemoryPool(int param1)
        : stuff(param1)
    {}

private:
    T stuff;
};

template<class T>
class CList
{
public:
    struct Entry
    {
        T data;
    };

    static CMemoryPool<Entry> s_pool;
};

template<class T>
CList<T>::CMemoryPool<CList<T>::Entry>::s_pool(1);

int main()
{
    CList<int> list;
}

Кажется, я не могу получить инициализацию s_pool вне класса для компиляции. Может ли кто-нибудь помочь мне понять, как это сделать? Примечание. Я использую только C++03.


person void.pointer    schedule 28.03.2014    source источник
comment
stackoverflow.com/questions/185844/   -  person Jeef    schedule 28.03.2014
comment
Об этом спрашивали много раз: - stackoverflow.com/questions/185844/ - stackoverflow.com/questions/8461546/   -  person Jeef    schedule 28.03.2014
comment
это для класса шаблонов, ваши ссылки на простые сценарии не отвечают на мой вопрос   -  person void.pointer    schedule 28.03.2014
comment
Просто используйте тип шаблона T   -  person Jeef    schedule 28.03.2014
comment
Почти уверен, что вам нужен typename для CList<T>::Entry, но, к сожалению, это тоже не помогло :( ...   -  person πάντα ῥεῖ    schedule 28.03.2014


Ответы (3)


РЕДАКТИРОВАТЬ: У меня сложилось впечатление, что:

Вы должны явно указать значение статического значения для каждого экземпляра шаблона:

CList<int>::CMemoryPool<CList<int>::Entry>::s_pool(1);

должно быть где-то в ваших файлах *.C...

В качестве альтернативы используйте статическую локальную переменную в методе таблицы, используемой для получения значения.

Но немного поиграв, кажется, что это компилируется в ideone

template<class T>
CMemoryPool<typename CList<T>::Entry> CList<T>::s_pool(1);

Я по-прежнему рекомендую решение @FredOverflow, поскольку оно защищает вас от статических проблем инициализации

person jsantander    schedule 28.03.2014
comment
Большинство других статических шаблонов можно инициализировать с типом T, так почему же мне нужно делать это явно для каждого типа в этом случае? - person void.pointer; 28.03.2014
comment
Ах, я чувствую себя глупо сейчас! В статической инструкции инициализации отсутствовал тип! Прекрасная работа! - person void.pointer; 28.03.2014
comment
@RobertDailey ... все еще ... Я не уверен, как это будет работать, если этот шаблон правильно определен в файле * .h и включен в несколько мест ... кто-нибудь знает? - person jsantander; 28.03.2014

Я думаю, что вы забыли, как вообще работает инициализация статического члена данных:

struct Data { int i; };

struct Holder { static Data StaticMember; };

Data Holder::StaticMember = { 1 };
^    ^~~~~~~~~~~~~~~~~~~~ static member qualified name
\~~~ static member type

Если вы посмотрите на свою декларацию, поразительно, что вы забыли одно из двух выше:

// Only a single element: there should be a type and a name
template<class T>
CList<T>::template CMemoryPool<typename CList<T>::Entry>::s_pool(1);

// Two elements
template<class T>
CMemoryPool<typename CList<T>::Entry> CList<T>::s_pool(1);
^                                     ^~~~~~~~~~~~~~~~ name
 \~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ type

После исправления все работает

person Matthieu M.    schedule 28.03.2014
comment
Сам код довольно запутан, поэтому я пропустил основную и фундаментальную часть. - person void.pointer; 28.03.2014
comment
Да, это проблема с появлением пробелов внутри типов: это выглядит правильно, но на самом деле это не так. Что меня подсказало, так это то, что в вашем объявлении CMemoryPool каким-то образом оказался вложенным типом внутри CList, что казалось подозрительным, и мне пришлось отступить, чтобы понять, что происходит на самом деле. - person Matthieu M.; 28.03.2014

Инициализировать статические данные-члены внутри шаблонов классов довольно сложно. Вместо этого я предлагаю заводскую функцию. Тогда вам не нужно беспокоиться об определении переменной где-то еще.

Просто перепишите строку

static CMemoryPool<Entry> s_pool;

to

static CMemoryPool<Entry>& s_pool()
{
    static CMemoryPool<Entry> foobar;
    return foobar;
}

А затем везде используйте s_pool() вместо s_pool. Вы получаете ленивую инициализацию в качестве преимущества.

person fredoverflow    schedule 28.03.2014
comment
Не отвечает на мой вопрос - person void.pointer; 28.03.2014
comment
@FredOverflow, вероятно, вам не хватает static CMemoryPool<Entry> foobar(1);, который заменил бы оригинальный CList<T>::CMemoryPool<CList<T>::Entry>::s_pool(1); - person jsantander; 28.03.2014
comment
@RobertDailey Я немного поигрался с вашим кодом и не смог понять его синтаксически правильно. Я бы сказал, что ответ Фреда хорошо отвечает на ваш вопрос, или, лучше сказать, элегантно решает вашу проблему. - person πάντα ῥεῖ; 28.03.2014
comment
Я не ищу элегантного решения, для меня это эксперимент (учебное упражнение). Я нашел эту проблему и не могу ее решить, было бы неплохо увидеть решение. Я понимаю, что есть альтернативные способы сделать то же самое, но это не то, о чем я прошу. - person void.pointer; 28.03.2014