Wie erstelle ich eine Vorlagenfunktion innerhalb einer Klasse? (C ++)

144

Ich weiß, dass es möglich ist, eine Vorlagenfunktion zu erstellen:

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

und es ist möglich, eine Vorlagenklasse zu erstellen:

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

Aber ist es möglich, eine Klasse nicht innerhalb einer Vorlage zu machen und dann eine Funktion in dieser Klasse zu einer Vorlage zu machen? Dh:

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

oder etwas in dem Maße, in dem die Klasse nicht Teil einer Vorlage ist, sondern die Funktion?


quelle

Antworten:

115

Ihre Vermutung ist die richtige. Das einzige, woran Sie denken müssen, ist, dass sich die Definition der Elementfunktionsvorlage (zusätzlich zur Deklaration) in der Header-Datei und nicht in der CPP befinden sollte, obwohl sie sich nicht im Hauptteil der Klassendeklaration selbst befinden muss.

Nicht sicher
quelle
3
Und auch, dass man sie nicht spezialisieren kann. :-(
Frank Krueger
7
Nicht genau richtig. Die Definition kann sich in einer CPP-Datei befinden, sofern sie für jeden eindeutigen Vorlagenparameter n-uplet von einer Nicht-Vorlagenfunktion / -methode nach ihrer Definition einmal aufgerufen wird.
Benoît
1
Daher ist mein "sollte" - es in der Kopfzeile zu halten, der einfachste Weg, dies zu erreichen.
Nicht sicher
4
Eigentlich glaube ich, dass Sie sie explizit spezialisieren können, aber Sie können sie nicht teilweise spezialisieren. Leider weiß ich nicht, ob dies eine compilerspezifische Erweiterung oder ein C ++ - Standard ist.
Patrick Johnmeyer
7
Es ist eigentlich Standard C ++. Sie können struct A {template <typename> void f () ausführen. }; template <> void A :: f <int> () {} zum Beispiel. Sie können sie einfach nicht auf den Klassenbereich spezialisieren, aber Sie können dies gut tun, wenn Sie dies im Namespace-Bereich tun. (Nicht zu verwechseln mit dem Bereich, in den die Spezialisierung tatsächlich eingefügt wird: Die Spezialisierung bleibt weiterhin Mitglied der Klasse - ihre Definition erfolgt jedoch im Namespace-Bereich. Oft entspricht der Bereich, in den etwas eingefügt wird, dem Bereich etwas ist definiert bei - aber das ist manchmal nicht wahr, wie in allen Fällen von Definitionen außerhalb der Klasse)
Johannes Schaub - litb
70

Siehe hier: Vorlagen , Vorlagenmethoden , Elementvorlagen, Elementfunktionsvorlagen

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];
}
keiner
quelle
gutes Beispiel. aber warum ist die Vorlage <Typname T> in der Klasse definitino ... ???
Martian2049
@ Martian2049 Ich glaube, dies ist so, dass die Vorlage nur für die Elementfunktion innerhalb der Klasse gilt und nicht für die Klasse als Ganzes. Genau wie das OP gefragt hat.
CBK
21

Ja, Vorlagenelementfunktionen sind bei zahlreichen Gelegenheiten vollkommen legal und nützlich.

Die einzige Einschränkung besteht darin, dass Vorlagenelementfunktionen nicht virtuell sein können.

Tobias
quelle
9

Der einfachste Weg besteht darin, die Deklaration und Definition in derselben Datei abzulegen. Dies kann jedoch zu einer übergroßen auslösbaren Datei führen. Z.B

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

Es ist auch möglich, die Vorlagendefinition in die separaten Dateien einzufügen, dh sie in CPP- und H-Dateien abzulegen. Alles, was Sie tun müssen, ist, die Vorlageninstanziierung explizit in die CPP-Dateien aufzunehmen. Z.B

// .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);
Hallo
quelle