Шаблонные специализации и статические локали - PullRequest
2 голосов
/ 29 января 2012

У меня есть класс X ...

class X {...}

и я хочу иметь один экземпляр X для каждого отдельного типа некоторого набора типов. (Некоторые из этих типов не являются классами и / или не написаны мной.)

Для этого я подумал:

template<typename T> X& XT();

, а затем для каждого типа A, B и C:

template<> X& XT<A>() { static X x; return x; }
template<> X& XT<B>() { static X x; return x; }
template<> X& XT<C>() { static X x; return x; }

Будет ли это работать? Это лучший способ сделать это? Какие есть альтернативные способы?

Ответы [ 2 ]

2 голосов
/ 29 января 2012

Вам не нужно специализировать функцию.Вы можете просто сделать это:

template<typename T> 
X& XT() 
{ 
    static X x; 
    return x; 
}

И использовать его как:

X &xa = XT<A>();
X &xb = XT<B>();
X &xc = XT<C>();
X &xd = XT<A>(); //xd is same as xa

Все три объекта xa, xb и xc являются различными экземплярами X. Однако, xa и xd являются одинаковыми экземплярами, так как они оба вызывают одну и ту же функцию.

Здесь необходимо отметить, что компилятор создает разные функции для каждого другого аргумента шаблона.Так что XT<A>() - это функция, отличная от XT<B>(), и каждая функция имеет свои собственные static локальные переменные.Таким образом, локальная переменная static в XT<A>() является экземпляром, отличным от переменной в XT<B>().

0 голосов
/ 29 января 2012

Вам даже не нужно определять каждое из них по отдельности:

#include <iostream>

template<typename T, typename X>
struct static_holder {
    static T static_instance;
};

template<typename T, typename X>
T static_holder<T,X>::static_instance;

template<typename T, typename X>
T &get_static_instance() {
    return static_holder<T,X>::static_instance;
}

Теперь вы можете просто определить:

template<typename K>
X &XT() {
    return get_static_instance<X, K>();
}

Обратите внимание, что эта техника может плохо работать, если используетсяграницы общей библиотеки.

...