Làm thế nào để tạo một hàm mẫu trong một lớp? (C ++)


144

Tôi biết có thể tạo một hàm mẫu:

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

và có thể tạo một lớp mẫu:

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

nhưng có thể tạo một lớp không nằm trong một mẫu và sau đó tạo một hàm trong lớp đó thành một mẫu không? I E:

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

hoặc một cái gì đó đến mức, trong đó lớp không phải là một phần của mẫu, nhưng chức năng là?

Câu trả lời:


115

Dự đoán của bạn là chính xác. Điều duy nhất bạn phải nhớ là định nghĩa mẫu hàm thành viên (ngoài khai báo) phải nằm trong tệp tiêu đề, không phải là cpp, mặc dù nó không phải nằm trong phần thân của khai báo lớp.


3
Và bạn cũng không thể chuyên môn hóa chúng. :-(
Frank Krueger

7
Không chính xác. Định nghĩa có thể nằm trong một tệp cpp, miễn là nó được gọi một lần cho mỗi tham số mẫu duy nhất n-uplet từ một phương thức / hàm không phải khuôn mẫu sau khi nó được xác định.
Benoît

1
Do đó "nên" của tôi - giữ nó trong tiêu đề là cách đơn giản nhất để thực hiện điều đó.
Không chắc

4
Trên thực tế, tôi tin rằng bạn có thể chuyên môn hóa chúng một cách rõ ràng, nhưng bạn không thể chuyên môn hóa chúng một phần. Thật không may, tôi không biết đây là phần mở rộng dành riêng cho trình biên dịch hay tiêu chuẩn C ++.
Patrick Johnmeyer

7
Đó thực sự là tiêu chuẩn c ++. Bạn có thể thực hiện struct A {template <typename> void f (); }; mẫu <> void A :: f <int> () {} chẳng hạn. Bạn không thể chuyên môn hóa chúng trong phạm vi lớp, nhưng bạn có thể làm tốt như vậy khi được thực hiện trong phạm vi không gian tên. (đừng nhầm lẫn với phạm vi mà chuyên môn hóa thực sự được đưa vào: chuyên môn vẫn sẽ là một thành viên của lớp - nhưng định nghĩa của nó được thực hiện trong phạm vi không gian tên. Thường thì phạm vi mà một cái gì đó được đưa vào giống như phạm vi một cái gì đó được định nghĩa tại - nhưng điều đó đôi khi không đúng, như trong tất cả các trường hợp định nghĩa ngoài lớp học)
Johannes Schaub - litb

70

Xem tại đây: Mẫu , phương thức mẫu , Mẫu thành viên, Mẫu chức năng thành viên

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

ví dụ tốt. nhưng tại sao mẫu <typename T> lại nằm trong lớp definitino ... ???
Sao Hỏa2049

@ Martian2049 Tôi tin rằng điều này là do đó mẫu chỉ áp dụng cho hàm thành viên trong lớp chứ không phải toàn bộ lớp. Chính xác như OP yêu cầu.
CBK

21

Có, các chức năng thành viên mẫu là hoàn toàn hợp pháp và hữu ích trong nhiều trường hợp.

Nhắc nhở duy nhất là các chức năng thành viên mẫu không thể là ảo.


9

Cách dễ nhất là đặt khai báo và định nghĩa trong cùng một tệp, nhưng nó có thể gây ra tệp kích thước quá cỡ. Ví dụ

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

Ngoài ra, có thể đặt định nghĩa mẫu trong các tệp riêng biệt, nghĩa là đặt chúng trong các tệp .cpp và .h. Tất cả những gì bạn cần làm là bao gồm rõ ràng việc khởi tạo mẫu vào các tệp .cpp. Ví dụ

// .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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.