2010-09-22 35 views
6

Hallo!C++ đơn mẫu chuyên môn với nhiều thông số mẫu

Tôi muốn chỉ chuyên về một trong hai loại mẫu. Ví dụ. template <typename A, typename B> class X nên có triển khai đặc biệt cho một hàm duy nhất X<float, sometype>::someFunc().

Mẫu mã:

main.h:

#include <iostream> 

template <typename F, typename I> 
class B 
{ 
public: 
    void someFunc() 
    { 
     std::cout << "normal" << std::endl; 
    }; 

    void someFuncNotSpecial() 
    { 
     std::cout << "normal" << std::endl; 
    }; 
}; 

template <typename I> 
void B<float, I>::someFunc(); 

main.cpp:

#include <iostream> 
#include "main.h" 

using namespace std; 

template <typename I> 
void B<float, I>::someFunc() 
{ 
    cout << "special" << endl; 
} 

int main(int argc, char *argv[]) 
{ 
    B<int, int> b1; 
    b1.someFunc(); 
    b1.someFuncNotSpecial(); 

    B<float, int> b2; 
    b2.someFunc(); 
    b2.someFuncNotSpecial(); 
} 

Compilation không cho class B. Có đúng, rằng điều này là không thể trong C + + theo cách này? Điều gì sẽ là giải pháp tốt nhất?

[sửa]

template <float, typename I> void B<float, I>::someFunc(); dẫn đến main.h: 26: lỗi: 'phao' không phải là một loại hợp lệ cho một tham số liên tục mẫu

template <typename I> void B<float, I>::someFunc(); dẫn đến main.h: 27: lỗi: sử dụng không hợp lệ loại không đầy đủ 'class B'

Và tôi đang sử dụng gcc.

[sửa]

Tôi không muốn chuyên toàn bộ lớp vì có các chức năng khác không có chuyên môn.

+0

Mẫu lớp A có liên quan đến câu hỏi của bạn không? – Doug

+0

Tôi nghĩ rằng nó sẽ làm cho câu hỏi dễ hiểu hơn. Tôi sẽ loại bỏ nó. – tauran

+0

Điều này đã được hỏi hàng trăm lần trên stackoverflow :) Tôi nghĩ rằng một số người trong chúng ta có thể thiết lập một câu hỏi thường gặp mẫu thực với những câu hỏi như vậy. Mọi người có thể kiểm tra faq để xem câu hỏi của họ có được trả lời hay không, thay vì phải tìm kiếm một bản dupe. –

Trả lời

16

Bạn phải cung cấp một phần chuyên môn hóa của lớp mẫu B:

template <typename I> 
class B<float, I> 
{ 
public: 
    void someFunc(); 
}; 

template <typename I> 
void B<float, I>::someFunc() 
{ 
    ... 
} 

Bạn cũng có thể chỉ định nghĩa someFunc bên trong chuyên môn.

Tuy nhiên, nếu bạn chỉ muốn chuyên chức năng và không phải là lớp làm e. g.

template <typename F, typename I> 
void someFunc(F f, I i) { someFuncImpl::act(f, i); } 

template <typename F, typename I> 
struct someFuncImpl { static void act(F f, I i) { ... } }; 

// Partial specialization 
template <typename I> 
struct someFuncImpl<float, I> { static void act(float f, I i) { ... } }; 

Nhưng bạn không thể chuyên mẫu chức năng mà không có thủ thuật này.

+1

Bạn không thể biết điều này. Nhưng trong trường hợp sử dụng của tôi, có rất nhiều chức năng khác không có chuyên môn. Với cách tiếp cận này, tôi sẽ phải nhân đôi tất cả các chức năng này. – tauran

+1

@tauran: Bạn không thể cung cấp các chuyên môn từng phần cho các mẫu chức năng. Chỉ dành cho các mẫu lớp và bạn phải cung cấp lại định nghĩa cho cả lớp. Sống với nó, hoặc xem câu trả lời cập nhật. –

+0

Bạn có thể giải quyết thêm một điều nữa trong mã của tauran không? Có 'mẫu void B :: someFunc();' ở cuối 'main.h'. Tôi nghĩ tauran muốn tuyên bố, rằng có một chuyên môn được định nghĩa ở đâu đó, trong một đơn vị biên dịch khác. Điều đó không yêu cầu các mẫu được xuất? Nếu chuyên môn hóa có nghĩa là, để được hiển thị trong tất cả các đơn vị biên dịch, 'main.h' được bao gồm trong, nó không phải nằm trong tiêu đề? –

5

Although you can totally specialize member functions of a class template, you cannot _partially specialize member functions. - Andrei Alexandrescu

phần Lớp chuyên môn được giải thích bởi các áp phích khác.

Bạn có thể, tuy nhiên, sử dụng quá tải:

template <class T, class U> T fun(U obj); // primary template 
template <class U> void Fun<void, U>(U obj); // illegal pertial 
// specialization 
template <class T> T fun (Window obj); // legal (overloading) 

Nếu bạn muốn đi sâu vào điều này, bạn có thể đọc về vấn đề này trong chiều sâu trong "Modern C++ Design" của A. Alexandrescu.

+0

+1 để gọi lại quá tải mẫu. Đây là một công cụ mà tôi hiếm khi nghĩ về việc sử dụng, nhưng công việc nào trong một số tình huống. –

0

Giải pháp 1. di chuyển tất cả triển khai sang lớp cơ sở như B_Base. sau đó chuyên về float để ghi đè someFunc. như bên dưới

template <typename F, typename I> 
    class B : B_Base<F, I> 
    { 
    } 

    template <typename I> 
    class B<float, I> : B_Base<flat, I> 
    { 
    public: 
     void someFunc() {....} 
    }; 

Giải pháp 2. sử dụng chức năng quá tải, đặt nổi làm đầu vào hoặc tăng :: is_same để gửi đi.thật không may, bạn có chức năng someFunc không có tham số. vì vậy nó cần thay đổi giao diện.

Các vấn đề liên quan