Формат специализации шаблона функции
-
06-09-2019 - |
Вопрос
В чем причина вторых скобок <> в следующем шаблоне функции:
template<> void doh::operator()<>(int i)
Это появилось в ТАК вопрос где было высказано предположение, что после operator()
, однако я не смог найти объяснения.
Я понимаю смысл, если бы это была типовая специализация (полная специализация) вида:
template< typename A > struct AA {};
template<> struct AA<int> {}; // hope this is correct, specialize for int
Однако для шаблонов функций:
template< typename A > void f( A );
template< typename A > void f( A* ); // overload of the above for pointers
template<> void f<int>(int); // full specialization for int
Где это вписывается в этот сценарий?:
template<> void doh::operator()<>(bool b) {}
Пример кода, который работает и не выдает никаких предупреждений/ошибок (используется gcc 3.3.3):
#include <iostream>
using namespace std;
struct doh
{
void operator()(bool b)
{
cout << "operator()(bool b)" << endl;
}
template< typename T > void operator()(T t)
{
cout << "template <typename T> void operator()(T t)" << endl;
}
};
// note can't specialize inline, have to declare outside of the class body
template<> void doh::operator()(int i)
{
cout << "template <> void operator()(int i)" << endl;
}
template<> void doh::operator()(bool b)
{
cout << "template <> void operator()(bool b)" << endl;
}
int main()
{
doh d;
int i;
bool b;
d(b);
d(i);
}
Выход:
operator()(bool b)
template <> void operator()(int i)
Решение
Я посмотрел и обнаружил, что это указано в 14.5.2/2:
Локальный класс не должен иметь шаблонов членов.Правила контроля доступа (пункт 11) применяются к именам шаблонов участников.Деструктор не должен быть шаблоном-членом.В классе могут быть объявлены как обычная (не шаблонная) функция-член с заданным именем и типом, так и шаблон функции-члена с тем же именем, который можно использовать для создания специализации того же типа.Если оба существуют, использование этого имени и типа относится к элементу, не являющемуся шаблоном, если не указан явный список аргументов шаблона.
И это приводит пример:
template <class T> struct A {
void f(int);
template <class T2> void f(T2);
};
template <> void A<int>::f(int) { } // non-template member
template <> template <> void A<int>::f<>(int) { } // template member
int main()
{
A<char> ac;
ac.f(1); //non-template
ac.f(’c’); //template
ac.f<>(1); //template
}
Обратите внимание, что в стандартных терминах specialization
относится к функции, которую вы пишете с использованием явной специализации, и к функции, сгенерированной с использованием создания экземпляра, и в этом случае мы имеем дело с сгенерированной специализацией. specialization
относится не только к функциям, которые вы создаете с использованием явной специализации шаблона, для чего он часто и используется.
Заключение:GCC ошибается.Комо, с помощью которого я также тестировал код, делает все правильно и выдает диагностику:
"ComeauTest.c"
, строка 16:ошибка:"void doh::operator()(bool)"
не является сущностью, которая может быть явно специализированаtemplate<> void doh::operator()(bool i)
Обратите внимание, что он не жалуется на специализацию шаблона для int
(только для bool
), поскольку оно не относится к тому же имени и тип:Тип функции, которую будет иметь специализация: void(int)
, который отличается от типа функции функции-члена, не являющейся шаблоном, которая void(bool)
.