2009-07-12 19 views
31

En C++, ¿puede tener un operador de plantilla en una clase? De este modo:Plantilla de función con un operador

class MyClass { 
public: 
    template<class T> 
    T operator()() { /* return some T */ }; 
} 

En realidad, esto parece compilar muy bien, pero la confusión viene en cómo se podría utilizar:

MyClass c; 
int i = c<int>(); // This doesn't work 
int i = (int)c(); // Neither does this* 

El hecho de que se compila en absoluto me sugiere que es factible, ¡No sé cómo usarlo! ¿Alguna sugerencia o es este un método de uso no inicial?

+1

¿Qué significa "esto no funciona/tampoco lo hace"? ¿Lo que pasa? –

+0

El compilador te critica, eso es lo que pasa :) – Toji

+0

Juro que he visto esta pregunta en SO antes ... No puedo encontrarla, así que obviamente uno no puede culparte. – GManNickG

Respuesta

41

Debe especificar T.

int i = c.operator()<int>(); 

Desafortunadamente, no puede usar la sintaxis de llamada de función directamente en este caso.

Editar: Ah, y te falta public: al principio de la definición de la clase.

+1

Agradable.¡Felicitaciones por la respuesta rápida y precisa! Desafortunadamente, eso es probablemente muy detallado para mis usos (ya que mi código debe ser llamado por otros para evitar confusiones), así que tendré que encontrar otra ruta. ¡Gracias de nuevo! – Toji

+5

Sí, probablemente sea mejor que defina un método 'get' en lugar de' operator() '. Entonces podrías escribir 'c.get ()'. – avakar

+0

En realidad, hay una expresión idiomática volando que muchos usan: función get gratuita (las tuplas usan 'get (some_tuple)', boost.variant usa 'get (some_variant)'). Así que el suyo se vería como 'obtener (c)', con 'get' siendo definido en el espacio de nombres 'MyClass'es'). –

18

Tienes razón. Es legal definir operadores con plantilla, pero no pueden invocarse directamente con argumentos de plantilla explícitos.

Si usted tiene este operador:

template <typename T> 
T operator()(); 

como en el ejemplo, que sólo puede ser llamado como esto:

int i = c.operator()<int>(); 

Por supuesto, si el argumento de plantilla se puede deducir a partir de los argumentos , todavía podría llamarlo de la manera normal:

template <typename T> 
T operator()(T value); 

c(42); // would call operator()<int> 

Una alternativa podría ser hacer el ar gument una referencia, y almacenar la salida de allí, en lugar de devolverlo:

template <typename T> 
void operator()(T& value); 

Así que en lugar de esto:

int r = c.operator()<int>(); 

que podría hacer

int r; 
c(r); 

O tal vez sólo debe definir una función simple get<T>() en lugar de usar el operador.

4

¿No estás pensando en

class Foo { 
    public: 
    template<typename T> 
    operator T() const { return T(42); } 
}; 

Foo foo; 

int i = (int) foo; // less evil: static_cast<int>(foo); 

live example. Esto demuestra que no necesita especificar el argumento de la plantilla, a pesar del reclamo en la respuesta aceptada.

+0

Funciona en este caso, pero estaba pensando en 'c ++'. Quiero decir que esto no debería funcionar, y estoy abusando de la notación allí ... – kim366

+0

@ kim366: Como eso no tiene sentido, no tiene sentido pensarlo. No debería funcionar, y no funciona. – MSalters

+0

Sí, estoy al tanto de eso .. Parece genial, sin embargo: P – kim366

Cuestiones relacionadas