Вопрос

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top