Як створити функцію шаблону в класі? (C ++)


144

Я знаю, що можна зробити функцію шаблону:

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

і можна зробити клас шаблонів:

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

але чи можна зробити клас не в шаблоні, а потім зробити функцію в цьому класі шаблоном? Тобто:

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

або щось в тій мірі, коли клас не є частиною шаблону, а функцією є?

Відповіді:


115

Ваша здогадка є правильною. Єдине, що вам потрібно пам’ятати, це те, що визначення шаблону функції члена (крім декларації) має бути у файлі заголовка, а не в cpp, хоча воно не повинно бути в тілі самої декларації класу.


3
А також, що ви не можете їх спеціалізувати. :-(
Френк Крюгер

7
Не зовсім правда. Визначення може бути у файлі cpp, якщо воно викликається один раз для кожного унікального параметра шаблону n-uplet з нешаблонної функції / методу після його визначення.
Benoît

1
Звідси моє "повинно" - зберігати його в заголовку - це найпростіший спосіб досягти цього.
Не впевнений,

4
Власне, я вважаю, що ви можете їх явно спеціалізувати, але частково не можете їх спеціалізувати. На жаль, я не знаю, чи це специфічне для компілятора розширення чи стандарт C ++.
Патрік Джонмайєр

7
Це фактично стандартний c ++. Ви можете зробити структуру A {template <typename> void f (); }; шаблон <> void A :: f <int> () {}, наприклад. Ви просто не можете спеціалізувати їх у межах класу, але ви можете зробити це добре, коли це зроблено в області простору імен. (не плутати з областю, в яку насправді вкладається спеціалізація: спеціалізація все одно буде членом класу - але її визначення робиться в області простору імен. Часто область, де щось вводиться, така ж, як і область застосування щось визначено на - але це іноді не відповідає дійсності, як у всіх випадках позакласних визначень)
Йоханнес Шауб - ліб

70

Дивіться тут: Шаблони , методи шаблонів , Шаблони членів, Шаблони функцій учасників

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];
}

хороший приклад. але чому шаблон <typename T> знаходиться всередині класу definitino ... ???
Martian2049

@ Martian2049 Я вважаю, що це так, що шаблон застосовується лише до функції члена в класі, а не до класу в цілому. Саме так, як просив ОП.
CBK

21

Так, функції членів шаблону є цілком законними та корисними у багатьох випадках.

Єдине застереження полягає в тому, що функції члена шаблону не можуть бути віртуальними.


9

Найпростіший спосіб - помістити декларацію та визначення в один і той же файл, але це може спричинити надмірний виправний файл. Напр

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

Також можна вказати визначення шаблону в окремі файли, тобто помістити їх у файли .cpp та .h. Все, що вам потрібно зробити - це явно включити екземпляр шаблону до файлів .cpp. Напр

// .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);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.