Jak stworzyć funkcję szablonu w klasie? (C ++)

144

Wiem, że można utworzyć funkcję szablonu:

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

i można zrobić klasę szablonową:

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

ale czy możliwe jest uczynienie klasy nie wewnątrz szablonu, a następnie uczynienie funkcji z tej klasy szablonem? To znaczy:

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

czy coś do tego stopnia, że ​​klasa nie jest częścią szablonu, ale funkcja jest?


źródło

Odpowiedzi:

115

Twoje przypuszczenie jest prawidłowe. Jedyną rzeczą, o której musisz pamiętać, jest to, że definicja szablonu funkcji składowej (oprócz deklaracji) powinna znajdować się w pliku nagłówkowym, a nie w cpp, chociaż nie musi znajdować się w treści samej deklaracji klasy.

Niepewny
źródło
3
A także, że nie możesz ich specjalizować. :-(
Frank Krueger
7
Nie do końca prawda. Definicja może znajdować się w pliku CPP, o ile jest wywoływana raz dla każdego unikalnego parametru szablonu n-uplet z funkcji / metody innej niż szablon po jej zdefiniowaniu.
Benoît
1
Stąd moje „powinno” - trzymanie go w nagłówku jest najprostszym sposobem na osiągnięcie tego.
Nie jestem pewien,
4
Właściwie uważam, że możesz wyraźnie je specjalizować, ale nie możesz wyspecjalizować się częściowo. Niestety nie wiem, czy jest to rozszerzenie specyficzne dla kompilatora, czy standard C ++.
Patrick Johnmeyer
7
W rzeczywistości jest to standardowe C ++. Możesz zrobić struct A {template <typename> void f (); }; Na przykład template <> void A :: f <int> () {}. Po prostu nie możesz ich specjalizować w zakresie klas, ale możesz to zrobić dobrze, gdy skończysz w zakresie przestrzeni nazw. (nie mylić z zakresem, w którym specjalizacja jest faktycznie umieszczona: specjalizacja nadal będzie członkiem klasy - ale jej definicja jest wykonywana w zakresie przestrzeni nazw. Często zakres, w którym coś jest umieszczane, jest taki sam jak zakres coś jest zdefiniowane w - ale to czasami nie jest prawdą, jak we wszystkich przypadkach definicji poza klasą)
Johannes Schaub - litb
70

Zobacz tutaj: Szablony , metody szablonów , Szablony składowe , Szablony funkcji składowych

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];
}
Żaden
źródło
dobry przykład. ale dlaczego szablon <typename T> znajduje się wewnątrz klasy definitino ... ???
Martian2049
@ Martian2049 Myślę, że tak jest, więc szablon ma zastosowanie tylko do funkcji składowej w klasie, a nie do klasy jako całości. Dokładnie tak, jak poprosił PO.
CBK
21

Tak, funkcje członków szablonu są w wielu przypadkach całkowicie legalne i przydatne.

Jedynym zastrzeżeniem jest to, że funkcje składowe szablonu nie mogą być wirtualne.

Tobias
źródło
9

Najłatwiej jest umieścić deklarację i definicję w tym samym pliku, ale może to spowodować zbyt duży plik wykonywalny. Na przykład

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

Możliwe jest również umieszczenie definicji szablonu w oddzielnych plikach, tj. Umieszczenie ich w plikach .cpp i .h. Wszystko, co musisz zrobić, to jawnie dołączyć wystąpienie szablonu do plików .cpp. Na przykład

// .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);
Hej
źródło