Когда мне нужно указать тип во втором <> шаблонной специализации?
У меня есть базовый шаблон:
template <class X> void f(X x) {}
Теперь я видел два способа специализировать это:
template <> void f<>(int x) {}
Или же:
template <> void f<int>(int x) {}
gcc ест оба варианта, но не оба одновременно.
Являются ли эти две специализации одинаковыми? Когда мне нужно указывать тип во втором <> при специализации шаблона?
2 ответа
Оба ваших варианта выполняют одну и ту же специализацию. Вы также можете использовать третий вариант
template <> void f(int x) {}
который также будет специализировать шаблон функции для X = int
, Это эквивалентно вашему второму варианту.
Варианты с f<>
и просто f
полагаться на вывод аргумента шаблона, в то время как f<int>
Вариант явно указывает аргумент шаблона.
Возможно, вам придется указать тип в <>
явно, когда вывод аргумента шаблона невозможен. В других случаях вам не нужно это делать.
Например, если список аргументов вашей функции не зависит от параметра шаблона X
тогда у вас не будет другого выбора, кроме как явно указать аргумент шаблона
template <typename X> void bar() {}
template <> void bar<int>() {}
Вышеуказанные компиляции. Но если вы замените специализацию на
template <> void bar<>() {}
он не сможет скомпилироваться, потому что компилятор не может определить аргумент шаблона.
Две специализации одинаковы. template<>
всегда специализирует существующий шаблон, а не объявляет новую подпись. Если вычет из типов параметров специализации может определить, что происходит внутри <>
тогда вы можете пропустить эту часть. (Пропускать такие вещи может быть плохой идеей, если есть больше шаблонных перегрузок. Может стать неясным, какой шаблон специализируется.)
Кстати, специализация функций, как правило, плохая идея. При разрешении перегрузки предпочтение будет отдано не шаблонной перегрузке, и оно будет эффективно скрывать специализацию, которую вы хотите предотвратить. Вместо того, чтобы комбинировать механизмы перегрузки и специализации, просто придерживайтесь перегрузки.