2009-06-02 5 views
30

¿Cuál es la razón de las segundas ménsulas <> en la plantilla de función siguiente:Función

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

Esto ocurrió en SO question donde se sugirió que hay entre paréntesis que faltan después de operator(), sin embargo pude no encuentras la explicación

entiendo el significado si se tratara de una especialización tipo (completa especialización) de la forma:

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

Sin embargo para las plantillas de función:

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 

Dónde encaja esto en este scenarion ?:

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

Código de ejemplo que parece funcionar y no da ningún wa rnings/error (gcc 3.3.3 usado):

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

Salida:

operator()(bool b) 
template <> void operator()(int i) 
+0

la sintaxis anterior de doble paréntesis es muy extraña. Normalmente he visto operator (bool b), pero ¿cómo funciona el operador() (bool b)? ¿Cuál es el uso de first empty()? – Jimm

+1

@Jimm el nombre del método es 'operator()' y toma un parámetro 'bool b' ... es el operador de llamada de función. Ver 'main' en mi ejemplo de código,' d (b) ' – stefanB

Respuesta

31

He mirado hacia arriba, y encontró que se especifica mediante 14.5.2/2:

A local class shall not have member templates. Access control rules (clause 11) apply to member template names. A destructor shall not be a member template. A normal (non-template) member function with a given name and type and a member function template of the same name, which could be used to generate a specialization of the same type, can both be declared in a class. When both exist, a use of that name and type refers to the non-template member unless an explicit template argument list is supplied.

Y proporciona un ejemplo:

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 
} 

Nótese que en S Los términos estándar, specialization se refieren a la función que se escribe utilizando una especialización explícita y a la función generada mediante instanciación, en cuyo caso tenemos que ver con una especialización generada. specialization no solo se refiere a las funciones que crea usando explícitamente la especialización de una plantilla, para la cual a menudo solo se usa.

Conclusión: GCC se equivoca. Comeau, con la que yo también probé el código, lo hace bien y emite un diagnóstico:

"ComeauTest.c" , line 16: error: "void doh::operator()(bool)" is not an entity that can be explicitly specialized template<> void doh::operator()(bool i)

en cuenta que no se queja de la especialización de la plantilla para int (sólo para bool), ya que doesn' t se refieren al mismo nombre y tipo: El tipo de función que la especialización tendría es void(int), que es distinto del tipo de función de la función miembro no plantilla, que es void(bool).

+0

Así que si sigo correctamente el 'miembro de plantilla' anterior es un miembro con plantilla en" especialización de struct A para int ". Tiene sentido ahora, por lo que al llamar a ac.f() se hará su propia resolución de plantilla basada en el parámetro o la lista de parámetros de plantilla explícita (cualquiera que sea el nombre correcto). – stefanB

+1

Sí, bueno, la especialización explícita que proporcionamos para f es para la especialización de struct A for int. la plantilla base general f existe para todas las especializaciones de A.Es por eso que también podemos llamarlo a A , como lo hace en main, por supuesto (pero no usará nuestra especialización explícita, ya que eso fue solo para A :: f !). Sí, ac.f (cosas) hace su propia resolución, de hecho. Aquí, consulte 14.8.1/2 ("Argumentos de la plantilla final que pueden deducirse ..."). Espero que esto ayude :) –

+0

Sí grandioso, gracias por la investigación :) – stefanB