Função formato de modelo de especialização
-
06-09-2019 - |
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)
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 especializadatemplate<> 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)
.