Comment créer une fonction de modèle au sein d'une classe? (C ++)

144

Je sais qu'il est possible de créer une fonction de modèle:

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

et il est possible de créer une classe de modèle:

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

mais est-il possible de créer une classe hors d'un modèle, puis de faire d'une fonction de cette classe un modèle? C'est à dire:

//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(){}
};

ou quelque chose dans la mesure où la classe ne fait pas partie d'un modèle, mais la fonction est?


la source

Réponses:

115

Votre estimation est la bonne. La seule chose dont vous devez vous souvenir est que la définition du modèle de fonction membre (en plus de la déclaration) doit être dans le fichier d'en-tête, pas dans le cpp, bien qu'elle ne doive pas être dans le corps de la déclaration de classe elle-même.

Pas certain
la source
3
Et aussi que vous ne pouvez pas les spécialiser. :-(
Frank Krueger
7
Pas exactement vrai. La définition peut être dans un fichier cpp, à condition qu'elle soit appelée une fois pour chaque paramètre de modèle unique n-uplet à partir d'une fonction / méthode non-modèle après avoir été définie.
Benoît le
1
D'où mon "devrait" - le garder dans l'en-tête est le moyen le plus simple d'accomplir cela.
Not Sure
4
En fait, je pense que vous pouvez les spécialiser explicitement, mais vous ne pouvez pas les spécialiser partiellement. Malheureusement, je ne sais pas s'il s'agit d'une extension spécifique au compilateur ou d'un standard C ++.
Patrick Johnmeyer
7
C'est en fait du c ++ standard. Vous pouvez faire struct A {template <typename> void f (); }; template <> void A :: f <int> () {} par exemple. Vous ne pouvez tout simplement pas les spécialiser dans la portée de la classe, mais vous pouvez le faire si bien lorsque vous le faites dans la portée de l'espace de noms. (à ne pas confondre avec la portée dans laquelle la spécialisation est réellement placée: la spécialisation sera toujours un membre de la classe - mais sa définition est faite dans la portée de l'espace de noms. Souvent, la portée dans laquelle quelque chose est placé est la même que la portée quelque chose est défini à - mais ce n'est parfois pas vrai, comme dans tous les cas de définitions hors classe)
Johannes Schaub - litb
70

Voir ici: Modèles , méthodes de modèle , modèles de membre, modèles de fonction de membre

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];
}
aucun
la source
bon exemple. mais pourquoi le template <typename T> est dans la classe definitino ... ???
Martian2049
@ Martian2049 Je pense que c'est ainsi que le modèle s'applique uniquement à la fonction membre au sein de la classe, et non à la classe dans son ensemble. Exactement comme le PO l'a demandé.
CBK
21

Oui, les fonctions des membres du modèle sont parfaitement légales et utiles à de nombreuses reprises.

La seule mise en garde est que les fonctions membres du modèle ne peuvent pas être virtuelles.

Tobias
la source
9

Le moyen le plus simple consiste à placer la déclaration et la définition dans le même fichier, mais cela peut entraîner un fichier excutable surdimensionné. Par exemple

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

De plus, il est possible de mettre la définition du modèle dans des fichiers séparés, c'est-à-dire de les placer dans des fichiers .cpp et .h. Tout ce que vous avez à faire est d'inclure explicitement l'instanciation du modèle dans les fichiers .cpp. Par exemple

// .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);
Hey
la source