2009-11-25 6 views
9

Я хочу, чтобы специализировать шаблон класса с помощью следующей функции:шаблон специализация с Шаблонным типом

template <typename T> 
class Foo 
{ 
public: 
    static int bar(); 
}; 

функция не имеет аргументов и возвращает результат, основанный на типе Foo. (В этом игрушечном примере мы возвращаем число байтов типа, но в реальном приложении мы хотим вернуть некоторый объект мета-данных.) специализация работает полностью определенных типов:

// specialization 1: works 
template <> 
int Foo<int>::bar() { return 4; } 

// specialization 2: works 
template <> 
int Foo<double>::bar() { return 8; } 

// specialization 3: works 
typedef pair<int, int> IntPair; 
template <> 
int Foo<IntPair>::bar() { return 2 * Foo<int>::bar(); } 

Однако, Я хотел бы обобщить это на типы, которые зависят от (других) параметров шаблона. Добавление следующей специализации дает ошибку во время компиляции (VS2005):

// specialization 4: ERROR! 
template <> 
template <typename U, typename V> 
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); } 

Я предполагаю, что это не законно C++, но почему? И есть ли способ реализовать этот тип рисунка элегантно?

+1

Заметим, однако, что вам не нужны никакие специализаций для возвращения размера T : 'static int Foo() {return sizeof (T); } '. Интересно, может ли такой шаблон не помочь вашей реальной проблеме. – UncleBens

ответ

7

Partitial специализация действительна только для классов, а не функции.

Обход:

template <typename U, typename V> 
class Foo<std::pair<U, V> > { 
public: 
static int bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
}; 

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

template<class T> 
struct aux { 
    static int bar(); 
}; 

template <>int aux <int>::bar() { return 4; } 
template <>int aux <double>::bar() { return 8; } 

template <typename U, typename V> 
struct aux <std::pair<U, V> > { 
    static int bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
}; 

template<class T> 
class Foo : aux<T> { 
    // ... 
}; 
+1

В примере все специализации являются специализациями классов – TimW

+1

Да. правильно. Функция partitial specialize запрещена. Можно создать базовый класс только для функциональной панели. –

+0

@TimW, в этом вопросе трюк заключается в том, что класс не специализирован.Это не соответствует стандарту: «Функция-член, класс-член или статический член данных шаблона класса может быть явно специализирован для специализированной специализации класса, которая неявно создается экземпляром, если такая явная специализация для члена имени шаблона класса неявно объявленная специальная функция-член (раздел 12), программа плохо сформирована ». Это специальность для одного заданного неявного экземпляра (таким образом, без зависимости параметра шаблона) этого шаблона (не для какой-либо частичной специализации). –

5

Это совершенно легально в C++, это Partial Template Specialization.
Снимите template <>, и если она не существует уже добавить явный шаблон класса специализации, и он должен собрать на VS2005 (но не в VC6)

// explicit class template specialization 
template <typename U, typename V> 
class Foo<std::pair<U, V> > 
{ 
public: 
    static int bar(); 
}; 

template <typename U, typename V> 
int Foo<std::pair<U, V> >::bar() { return Foo<U>::bar() + Foo<V>::bar(); } 
+1

@litb Насколько я могу видеть, все его функции - это специализации классов. Я не вижу никаких шаблонов функций, не так ли? – TimW

+0

@TimW: Когда вы объявляете шаблон класса, каждая функция-член является независимым шаблоном функции. ОП пытается специализировать шаблон функции-члена без специализации всего шаблона класса. В этом-то и дело. Однако частичная специализация не поддерживается для шаблонов функций. Это проблема. – AnT

+0

@TimW, нет шаблона функций. Но также нет специализированной специализации шаблонов классов. См. Выше стандартную цитату: это особый случай в стандарте и позволяет явно специализировать отдельные элементы без шаблонов шаблонов классов, не указывая явно их весь шаблон класса. Он работает, назвав данный неявный экземпляр (в его примере, например, «Foo » или «Foo '), который в отсутствие каких-либо частичных специализаций «Foo» будет выбирать первичный шаблон и специализировать его «бар». –

Смежные вопросы