2011-01-03 17 views
6

El siguiente fragmento de código funciona para mí:plantillas miembro de función y operador de sobrecarga() en C++

class Foo { 
public: 
    template <class T> T& get() { ... } 
}; 

Foo foo; 
foo.get<int>() = ...; 

Sin embargo, el siguiente fragmento de código no funciona para mí:

class Foo { 
public: 
    template <class T> T& operator()() { ... } 
}; 

Foo foo; 
foo<int>() = ...; 

Los errores siendo:

expected primary-expression before '>' token 
expected primary expression before ')' token 

Ambos errores se refieren a la foo<int>()

¿Por qué esto no funciona y es posible solucionarlo?

+1

Su plantilla 'operator()' es bastante inutilizable, ya que sus instancias se sobrecargarían solo con el valor de retorno. Sigue usando el nombre 'get' o similar. – aschepler

+0

No es inutilizable (aunque puede no ser preferible). Vea las respuestas a continuación. –

+0

¿Por qué estás templaizando las funciones pero no la clase como un todo? –

Respuesta

10

Si es necesario especificar explícitamente el argumento de plantilla, lo que tendría que utilizar la sintaxis operator:

foo.operator()<int>() 

No hay ninguna manera de especificar los argumentos que utilizan la sintaxis de la función de guardia. Si no puede deducir los argumentos de la plantilla de los argumentos a la función, es mejor usar una función miembro que una sobrecarga del operador.

+0

Ahh, de hecho, gracias. Tiene sentido ahora. – Dan

-1

alternativa usted puede hacer esto

class Foo { 
public: 
    template <class T> operator T&() { ... } 
}; 

Entonces se llamará automáticamente a la función correcta en función del tipo de "retorno":

Foo foo; 
int i=foo; 

Sé que la mayoría de las personas no les gusta esto como la función a la que se llama depende del tipo de devolución, pero considero que es un gran "truco" que a menudo limpia la sintaxis.

+3

Advertencia adicional: será fácil crear una instancia accidental de ese método de "conversión" con un tipo no deseado. – aschepler

+2

Creo que este es un truco que complica excesivamente el código. Ha proporcionado un operador de conversión para * cualquier * tipo ... ¡va a llegar a usted en el lugar más improbable donde no puede esperar ni darse cuenta! –

1

El problema es que la lista de parámetros de la plantilla está en el lugar equivocado; es como si estuviera tratando de usar un objeto o función llamada foo con el argumento de plantilla int, pero de hecho es el operator() que quiere que la lista de parámetros de la plantilla esté activada.

Desafortunadamente (posiblemente así, al menos), no hay forma de evitar esto con los operadores. Usted tiene que llamarlos como funciones completas:

class Foo { 
public: 
    template <class T> T& operator()() { ... } 
}; 

Foo foo; 
foo.operator()<int> = ...; 

Espero que esto ayude.