2010-07-29 34 views
7

Tôi có một mẫu mà tôi muốn biên dịch có điều kiện tùy thuộc vào loại đối số. Tôi chỉ quan tâm đến sự khác biệt giữa "Dữ liệu cũ thuần túy" (POD), tức là, số nguyên, v.v. hoặc các lớp/cấu trúc. Tôi đang sử dụng c + + VS2008 trên Windows.Biên dịch có điều kiện bằng cách sử dụng các đặc tính kiểu tăng cường

template<T> 
class foo 
{ 
    void bar(T do_something){ 
    #if IS_POD<T> 
     do something for simple types 
    #else 
     do something for classes/structs 
    #endif 
}} 

Tôi đã xem xét thư viện tăng cường và tôi có thể thấy rằng chúng dường như có những gì tôi muốn. Tuy nhiên, tôi không hiểu cú pháp chính xác cho câu lệnh #if là gì.

Mọi trợ giúp sẽ được đánh giá cao.


Chỉnh sửa --- Sau khi đọc câu trả lời, tôi thấy tôi đã bỏ qua điều gì đó trong định nghĩa của câu hỏi. Lớp foo là một lớp templated mà chỉ cần ví dụ phiên bản của bar đó là chính xác cho class type T. Tôi đã tìm kiếm một giải pháp có thể được giải quyết một thời gian biên dịch. Hy vọng điều này sẽ làm sáng tỏ vấn đề của tôi.

Trả lời

7

Bạn có thể làm điều đó mà không enable_if, bởi vì tất cả bạn cần là để gửi tùy thuộc vào đặc điểm loại. enable_if được sử dụng để thêm/xóa các mẫu tức thời đến/từ độ phân giải quá tải. Bạn có thể muốn sử dụng các đặc điểm cuộc gọi để chọn phương pháp tốt nhất để truyền đối tượng cho hàm của bạn. Theo quy định, các đối tượng phải được chuyển qua tham chiếu, trong khi POD được truyền theo giá trị. call_traits cho phép bạn chọn giữa các tham chiếu constkhông const. Mã bên dưới sử dụng tham chiếu const.

#include <boost/type_traits.hpp> 
#include <boost/call_traits.hpp> 

template <typename T> 
class foo { 
public: 
    void bar(typename boost::call_traits<T>::param_type obj) { 
     do_something(obj, boost::is_pod<T>()); 
    } 
private: 
    void do_something(T obj, const boost::true_type&) 
    { 
     // do something for POD 
    } 
    void do_something(const T& obj, const boost::false_type&) 
    { 
     // do something for classes 
    } 
}; 
0

Sử dụng bộ xử lý trước ở đây là không thể. Thay vào đó, hãy xem Boost Enable If library.

Cụ thể, trong trường hợp của bạn nó sẽ như thế nào (không kiểm tra):

void bar (typename enable_if <is_pod <T>, T>::type do_something) 
{ 
    // if is POD 
} 

void bar (typename disable_if <is_pod <T>, T>::type do_something) 
{ 
    // if not 
} 
+0

Đây sẽ là lỗi biên dịch, khi mẫu lớp được khởi tạo, 'T' được cố định và tại thời điểm đó khi bạn cố gắng gọi' bar', nó sẽ thấy hai định nghĩa và không biên dịch được một trong số chúng. Lưu ý rằng đây không phải là SFINAE, vì nó sẽ không phải là một sự thay thế thất bại - loại được cố định trước khi diễn giải của thành viên (hoặc vì vậy tôi nghĩ rằng, tôi không bao giờ chắc chắn với những điều này :)). –

3

Bạn không thể giải quyết điều này với các tiền xử lý, vì nó không biết về C++. (Đó là một công cụ thay thế văn bản câm.) Sử dụng các mẫu để thực hiện việc này.

Giả sử IsPod<T>::result lợi nhuận một cái gì đó giống nhau Boolean<true>/Boolean<false>:

template<T> 
class foo 
{ 
    void do_something(T obj, Boolean<true> /*is_pod*/) 
    { 
     // do something for simple types 
    } 
    void do_something(T obj, Boolean<false> /*is_pod*/) 
    { 
     // do something for classes/structs 
    } 

    void bar(T obj) 
    { 
     do_something(obj, IsPod<T>::result()); 
    } 
} 
Các vấn đề liên quan