¿Cómo crear una función de plantilla dentro de una clase? (C ++)

144

Sé que es posible hacer que una plantilla funcione:

template<typename T>
void DoSomeThing(T x){}

y es posible hacer una clase de plantilla:

template<typename T>
class Object
{
public:
    int x;
};

pero, ¿es posible hacer que una clase no esté dentro de una plantilla y luego convertir una función en esa clase en una plantilla? Es decir:

//I have no idea if this is right, this is just how I think it would look
class Object
{
public:
    template<class T>
    void DoX(){}
};

o algo en la medida en que la clase no es parte de una plantilla, pero la función sí?


fuente

Respuestas:

115

Tu suposición es la correcta. Lo único que debe recordar es que la definición de la plantilla de función miembro (además de la declaración) debe estar en el archivo de encabezado, no en el cpp, aunque no tiene que estar en el cuerpo de la declaración de la clase en sí.

No estoy seguro
fuente
3
Y también que no puedes especializarlos. :-(
Frank Krueger
77
No es exactamente cierto. La definición puede estar en un archivo cpp, siempre que se llame una vez para cada n-uplet de parámetro de plantilla único desde una función / método que no sea de plantilla después de que se haya definido.
Benoît
1
De ahí mi "debería": mantenerlo en el encabezado es la forma más sencilla de lograrlo.
No estoy seguro
44
En realidad, creo que puedes especializarlos explícitamente, pero no puedes especializarlos parcialmente. Lamentablemente, no sé si se trata de una extensión específica del compilador o del estándar C ++.
Patrick Johnmeyer
77
En realidad es c ++ estándar. Puede hacer la estructura A {template <typename> void f (); }; plantilla <> void A :: f <int> () {} por ejemplo. Simplemente no puede especializarlos en el alcance de la clase, pero puede hacerlo bien cuando se hace en el alcance del espacio de nombres. (no debe confundirse con el alcance en el que realmente se pone la especialización: la especialización seguirá siendo un miembro de la clase, pero su definición se realiza en el alcance del espacio de nombres. A menudo, el alcance donde se coloca algo es el mismo que el alcance algo se define en - pero eso a veces no es cierto, como en todos los casos de definiciones fuera de clase)
Johannes Schaub - litb
70

Consulte aquí: Plantillas , métodos de plantilla , Plantillas de miembros, Plantillas de funciones de miembros

class   Vector
{
  int     array[3];

  template <class TVECTOR2> 
  void  eqAdd(TVECTOR2 v2);
};

template <class TVECTOR2>
void    Vector::eqAdd(TVECTOR2 a2)
{
  for (int i(0); i < 3; ++i) array[i] += a2[i];
}
ninguna
fuente
buen ejemplo. pero ¿por qué la plantilla <typename T> está dentro de la clase definino ... ???
Martian2049
@ Martian2049 Creo que esto es así, la plantilla solo se aplica a la función miembro dentro de la clase, y no a la clase en su conjunto. Exactamente como preguntó el OP.
CBK
21

Sí, las funciones de miembro de plantilla son perfectamente legales y útiles en numerosas ocasiones.

La única advertencia es que las funciones miembro de la plantilla no pueden ser virtuales.

Tobias
fuente
9

La forma más fácil es colocar la declaración y la definición en el mismo archivo, pero puede causar un archivo ejecutable sobredimensionado. P.ej

class Foo
{
public:
template <typename T> void some_method(T t) {//...}
}

Además, es posible poner la definición de plantilla en los archivos separados, es decir, ponerlos en archivos .cpp y .h. Todo lo que necesita hacer es incluir explícitamente la creación de instancias de plantilla en los archivos .cpp. P.ej

// .h file
class Foo
{
public:
template <typename T> void some_method(T t);
}

// .cpp file
//...
template <typename T> void Foo::some_method(T t) 
{//...}
//...

template void Foo::some_method<int>(int);
template void Foo::some_method<double>(double);
Oye
fuente