Pergunta

Qual é a razão para a segunda colchetes <> no seguinte modelo de função:

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

Este surgiu em SO questão onde foi sugerido que há suportes desaparecidas após operator(), no entanto eu não conseguia encontrar a explicação.

Eu entendo o significado se fosse uma especialização tipo (especialização completo) da forma:

template< typename A > struct AA {};
template<> struct AA<int> {};         // hope this is correct, specialize for int

No entanto, para modelos de função:

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

Onde isso se encaixa nessa scenarion:?

template<> void doh::operator()<>(bool b) {}

Exemplo de código que parece trabalho e não dá qualquer avisos / erro (gcc 3.3.3 utilizado):

#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);
}

Output:

operator()(bool b)
template <> void operator()(int i)
Foi útil?

Solução

Eu olhei para cima, e descobriu que ele é especificado pelo 14.5.2 / 2:

A classe local não deve ter modelos membros. regras de controle de acesso (cláusula 11) aplicam-se a nomes de modelos membro. Um destruidor não deve ser um modelo de membro. A (não-molde) a função normal membro com um dado nome e o tipo e um modelo de função de membro do mesmo nome, o qual poderia ser usado para gerar uma especialização do mesmo tipo, podem ambos ser declarado de uma classe. Quando ambos existem, a utilização desse nome e tipo refere-se ao membro não-template a menos que uma lista de argumentos modelo explícita é fornecida.

E fornece um exemplo:

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
}

Note que em termos Padrão, specialization refere-se à função que escrever usando uma especialização explícita e para a função gerado usando instanciação, caso em que temos a ver com uma especialização gerado. specialization não se refere apenas às funções que você cria usando explicitamente especializados um modelo, para o qual é muitas vezes usado apenas.

Conclusão: GCC erra. Comeau, com o qual eu também testou o código, acerta e emite um diagnóstico:

"ComeauTest.c", linha 16: erro: "void doh::operator()(bool)" não é uma entidade que pode ser explicitamente especializada template<> void doh::operator()(bool i)

Note que não está reclamando sobre a especialização do modelo para int (apenas para bool), uma vez que não se referem ao mesmo nome e Tipo: O tipo de função que a especialização seria Já é void(int), que é diferente do tipo de função da função de membro não-molde, que é void(bool).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top