2012-06-13 26 views
10

Có cách nào để xác định loại biến được chuyển đến mẫu và gọi hàm dựa trên nếu đó là int hoặc std::string v.v ...?Thực hiện các phương pháp khác nhau dựa trên loại biến mẫu

Ví dụ

template <class T> 
struct Jam 
{ 
    Jam(T *var) 
    { 
     if (typeid(var) == typeid(std::string*) 
       *var = "Hello!"; 
     else if (typeid(var) == typeid(int*) 
       *var = 25; 
    } 
}; 

Khi tôi cố gắng sử dụng mã đó, tôi nhận được một lỗi invalid conversion from const char* to int. Tôi nghi ngờ điều này là do trình biên dịch "mở rộng" mẫu thành các hàm riêng biệt và khi tôi chỉ định một cá thể mới của cấu trúc throw Jam<std::string>(&setme);, nó phát hiện ra câu lệnh var* = 25 và từ chối biên dịch.

Có cách nào phù hợp để thực hiện việc này không? Có lẽ với bảo vệ macro? Cảm ơn.

Trả lời

12

Sử dụng chức năng thường xuyên quá tải thay vì:

template <class T> 
struct Jam 
{ 
    Jam(std::string* var) 
    { 
     *var = "Hello!"; 
    } 

    Jam(int* var) 
    { 
     *var = 25; 
    } 
}; 

trừ khi bạn muốn chuyên về các loại T sử dụng để nhanh chóng Jam. Trong trường hợp đó, bạn sẽ làm:

template<> 
struct Jam<std::string> 
{ 
    Jam(std::string* var) 
    { 
     *var = "Hello!"; 
    } 
}; 

template<> 
struct Jam<int> 
{ 
    Jam(int* var) 
    { 
     *var = 25; 
    } 
}; 


template<typename T> 
struct Jam 
{ 
    Jam(T* var) 
    { 
     // every other type 
    } 
}; 
+1

Có các lựa chọn thay thế khác, ví dụ chỉ chuyên về hàm tạo ('template <> Jam :: Jam (int * var) {}' bên ngoài định nghĩa lớp mẫu) hoặc SFINAE phức tạp hơn để bật/tắt mã dựa trên trên các đối số mẫu ... Tôi không nghĩ nó có ý nghĩa trong vấn đề đơn giản này, nhưng nó có thể có ý nghĩa khi các giải pháp đơn giản này trở thành gánh nặng (nói rằng hàm tạo đã làm 100 thứ, chỉ một trong số đó phụ thuộc vào kiểu , hoặc có 100 chức năng thành viên khác và chuyên loại toàn bộ sẽ là tốn kém) –

6

Tra cứu "chuyên môn mẫu từng phần".

Tham Jam() 's cơ thể ra khỏi Jam {}:

template <class T> 
struct Jam 
{ 
    Jam(T *var); 
}; 

Bây giờ viết hai cơ quan:

Jam<int>::Jam(int *var) { 
    // stuff 
} 

Jam<std::string>::Jam(std::string *var) { 
    // stuff 
} 

(Cảnh báo:. Rusty C++ Nhưng đó là nói chung như thế nào bạn làm điều đó.)

Câu hỏi mới: Nếu bạn cần gõ vịt, tại sao bạn sử dụng C++? Tôi muốn chuyển sang Ruby và lưu C++ cho các plugin cần tốc độ. Nhưng C++ vẫn sẽ hỗ trợ thiết kế thanh lịch, với nhiều công việc hơn!

+1

+1, mặc dù đây không phải là những gì thường được gọi là * partial * template specialization. Chuyên mục * partial * trong * partial template * thường đề cập đến thực tế là chuyên môn chỉ được áp dụng cho một tập hợp con các kiểu, so với * chuyên môn đầy đủ * mà tất cả các đối số mẫu được cố định. –

+2

Holy crap. Tôi biết C++? Hy vọng không có gì phát nổ! – Phlip

+0

@Phlip Tôi vừa sử dụng mã của bạn trong khởi chạy tàu con thoi. Nó bắt lửa, giết tất cả mọi người bên trong, và phá hủy một thành phố, tất cả vì mã của bạn. Cảm ơn rất nhiều. – Andrew

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