Запутаться с шаблоном C ++ - PullRequest
       41

Запутаться с шаблоном C ++

2 голосов
/ 17 января 2011

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

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

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

Ответы [ 4 ]

11 голосов
/ 17 января 2011

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

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*.

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

2 голосов
/ 17 января 2011
2 голосов
/ 17 января 2011

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

// 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 <>.

2 голосов
/ 17 января 2011

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

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

...