2011-01-17 6 views
2

Я смотрю на каком-Си ++ коде и не понимаю цели декларации шаблона в этой ситуации:путаться с шаблоном C++

template<> void operator>>(const ClassA& s, const ClassB d) {...} 

Что семантика template<>?

ответ

11

Это, действительно, специализированная специализация, как и другие, упомянутые ранее. Должен быть некоторый ранее объявленный шаблон функции, такой как:

template<typename T, typename U> 
void operator>>(const T& s, const U d) {...} 

Однако, это довольно ошибочно. Гораздо лучше удалить template<>, так что operator>> просто перегрузится. Проблема специализации шаблона заключается в том, что это может привести к неожиданному поведению при наличии перегруженных функций (и operator>> имеет много перегрузок), поскольку специализация не перегружает. Это означает, что компилятор сначала выбирает наиболее подходящую перегрузку для функции, а затем, если выбранная перегрузка является шаблоном функции, она ищет специализированные специализации, чтобы увидеть, есть ли соответствующий.

Классический пример (к сожалению, я не помню, где я его читал). Рассмотрим этот перегруженный шаблон функции:

template <typename T> 
void Function(T param); 

template <typename T> 
void Function(T* param); 

template <> 
void Function(int* param); 

main() 
{ 
    int i = 5; 
    Function(&i); 
} 

Как и ожидалось, специализация шаблона для int* называется. Но просто изменить порядок определений функций:

template <typename T> 
void Function(T param); 

template <> 
void Function(int* param); 

template <typename T> 
void Function(T* param); 

main() 
{ 
    int i = 5; 
    Function(&i); 
} 

Теперь общий шаблон для T* называется, так как мы специализируемся шаблон для T, а не для T*, и этот второй шаблон лучше подходит для нашего звонка. Это можно было бы избежать, если бы мы перегрузили функцию вместо специализировать шаблон:

void Function(int* param); 

Теперь порядок декларирования не имеет значения, мы всегда будем называть перегрузки для int*.

ОБНОВЛЕНИЕ: Теперь я знаю, кому кредит. Я читал об этом в article Херб Саттер. Пример был предоставлен Питером Димовым и Дейвом Абрахамом.

+0

Спасибо за ответ, так что это еще один трюк, который усложняет язык. Подобно перегрузке, я не думаю, что это хорошая идея: http://gbracha.blogspot.com/2009/09/systemic-overload.html – mathk

+0

@mathk: Я не согласен с большинством идей в статье, которую вы связываете. – Gorpik

+0

Вы не согласны с одним из тех парней, которые разрабатывают Java. Что тебе не нравится? – mathk

2

Это template specialization: (полностью или частично) разрешение шаблона для определенного типа. (Ваш конкретный пример, как представляется, полная специализация, так как нет больше параметров шаблона не остается нерешенной в нем. Если шаблон имеет несколько параметров, и вы специализируетесь только некоторые из них, это называется частичный шаблон специализации)

Это позволяет обеспечить оптимизацию типа, специфичный для данного шаблона или сделать много хитрых трюков, такими как обнаружение статического типа переменных и т.д.

+1

éter Я не думаю, что пример, представленный OP, действителен. Если я правильно помню, вы не можете специализировать функцию, вам нужно ее перегрузить. Специализация работает только для классов. – greatwolf

+1

@Victor, функции шаблона имеют некоторые ограничения по сравнению с шаблонами классов; dunno, как (и есть ли) это изменило C++ 03 и позже, хотя. Тем не менее, связанные примеры в C++ FAQ, похоже, являются специализированными функциями шаблонов, поэтому я полагаю, что он должен работать :-) –

+2

éter hmm interesting, я просто попробовал его на нескольких компиляторах и действительно принимает код. Похоже, что частичная специализация не работает на функции. Должно быть, это то, о чем я думал. – greatwolf

2

вы можете использовать этот синтаксис, если вы хотите, чтобы обеспечить a специальный обработчик для конкретной templa te type. Рассмотрим:

// A normal template definition. 
template <typename AType> 
whoami() { std::cout << "I am an unknown type."; } 

// Now we specialize. 
template <> 
whoami<int>() { std::cout << "I am an integer!"; } 

Там какая-то другая ерунда участвуют, в частности, «частичная специализация», но это основная функция template <>.

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