Подтвердить что ты не робот

Формат специализации шаблона функции

В чем причина вторых скобок < > в следующем шаблоне функции:

template<> void doh::operator()<>(int i)

Это появилось в SO вопрос, где было высказано предположение о том, что после 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)
4b9b3361

Ответ 1

Я просмотрел его и обнаружил, что он указан в 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).