2010-02-15 37 views
24

Trong chức năng ized mẫu của tôi, tôi đang cố gắng kiểm tra loại T là một loại cụ thể. Tôi sẽ làm như thế nào?Làm cách nào để kiểm tra lớp mẫu của tôi là một loại classtype cụ thể?

p/s Tôi biết cách đặc tả mẫu nhưng tôi không muốn làm điều đó.

template<class T> int foo(T a) { 
    // check if T of type, say, String? 
} 

Cảm ơn!

+3

Tại sao bạn không muốn "Mẫu đặc cách "? –

+3

Sử dụng "cách nạp chồng mẫu" :) –

+0

Bạn có thể nên kiểm tra hành vi, không nhập. – MSalters

Trả lời

7

Tôi cho rằng bạn có thể sử dụng std::type_info trả về bởi các nhà điều hành typeid

+0

dường như với tôi đây là những gì tôi cần. Cảm ơn rất nhiều! Sẽ thử nó ra – huy

+7

Cảnh báo: kiểm tra thời gian chạy. Như vậy, bạn không thể dựa vào các thuộc tính biên dịch thời gian. Ví dụ. bạn không thể chỉ sử dụng 'toán tử []' sau khi kiểm tra nếu T == std :: string. – MSalters

+1

@huy Thường tốt hơn là thực hiện kiểm tra tĩnh cho các loại thay vì kiểm tra thời gian chạy. Do đó, 'std :: is_same',' std :: is_convertible', hoặc tương tự. Sau đó, bạn có thể tránh chi phí thời gian chạy của việc kiểm tra loại. Thay vào đó, nếu chỉ một phần mã của bạn cần biết loại, hãy sử dụng 'if constexpr' (C++ 17) hoặc hàm trợ giúp; nếu tất cả các mã của bạn làm, sử dụng chức năng quá tải. –

48

Thay vì kiểm tra loại sử dụng chuyên môn. Nếu không, không sử dụng mẫu.

template<class T> int foo(T a) { 
     // generic implementation 
} 
template<> int foo(SpecialType a) { 
    // will be selected by compiler 
} 

SpecialType x; 
OtherType y; 
foo(x); // calls second, specialized version 
foo(y); // calls generic version 
+0

Thường là một ý tưởng tồi khi chuyên về các mẫu chức năng; chuyên môn từng phần không được hỗ trợ và nếu bạn kết hợp chuyên môn hóa và quá tải, bạn thường nhận được kết quả không mong muốn. Chỉ cần quá tải từ đầu. –

12

Nếu bạn không quan tâm đến thời gian biên dịch, bạn có thể sử dụng boost::is_same.

bool isString = boost::is_same<T, std::string>::value; 

Tính đến C++ 11, đây hiện là một phần của thư viện chuẩn

bool isString = std::is_same<T, std::string>::value 
+4

Đối với hồ sơ: [is_same] (http://en.cppreference.com/w/cpp/types/is_same) hiện là một phần của thư viện chuẩn. – kebs

2

Bạn có thể thực hiện kiểm tra tĩnh vào loại mà bạn đã nhận được (nhìn vào thư viện đặc điểm tăng type) , nhưng trừ khi bạn sử dụng chuyên môn (hoặc quá tải, như @litb chỉ ra chính xác) tại một điểm hay điểm khác, bạn sẽ không thể cung cấp các triển khai cụ thể khác nhau tùy thuộc vào loại đối số.

Trừ khi bạn có một lý do cụ thể (mà bạn có thể thêm vào câu hỏi) không sử dụng chuyên môn trong giao diện chỉ làm chuyên.

template <> int subtract( std::string const & str); 
6

Tôi nghi ngờ ai đó nên cho bạn biết lý do tại sao không nên sử dụng quá tải hoặc chuyên môn hóa. Xem xét:

template<class T> int foo(T a) { 
    if(isAString<T>()) { 
    return a.length(); 
    } else { 
    return a; 
    } 
} 

Bạn có thể nghĩ về một cái nhìn đầu tiên mà nó sẽ làm việc cho int quá, bởi vì nó sẽ chỉ cố gắng gọi length cho chuỗi. Nhưng trực giác đó là sai: Trình biên dịch vẫn kiểm tra nhánh chuỗi, ngay cả khi nhánh đó không được thực hiện trong thời gian chạy. Và nó sẽ tìm thấy bạn đang cố gắng gọi một chức năng thành viên trên các lớp không nếu T là một int.

Đó là lý do tại sao bạn nên tách mã nếu bạn cần hành vi khác. Nhưng tốt hơn sử dụng quá tải thay vì chuyên môn, vì nó dễ dàng hơn để có được một đầu mối làm thế nào những thứ làm việc với nó.

template<class T> int foo(T a) { 
    return a; 
} 

int foo(std::string const& a) { 
    return a.length(); 
} 

Bạn cũng đã tách mã tốt hơn cho các hành vi khác nhau. Nó không phải tất cả được gắn lại với nhau. Chú ý rằng với quá tải, các tham số có thể có các dạng khác nhau và trình biên dịch sẽ vẫn sử dụng đúng phiên bản nếu cả hai đều khớp nhau tốt, như trường hợp ở đây: Một có thể là một tham chiếu, trong khi khác thì không.

+0

Tôi gặp phải vấn đề bạn đã đề cập trước đó, đó là lý do tại sao tôi muốn tìm cách sửa lỗi, nhưng không phải quá tải hoặc chuyên môn hóa lớp. Tôi không nghĩ đến việc 'có được một đầu mối làm thế nào mọi thứ sẽ làm việc' một phần. Sẽ xem xét lại, cảm ơn! – huy

+0

@huy, bạn được chào đón. –

+0

Sửa đổi ví dụ của bạn bằng dàn diễn viên sẽ thực hiện thủ thuật. Nhưng nó vẫn không phải là giải pháp yêu thích của tôi :) –

9

hmm vì tôi có phần lớn cùng mã cho đến khi phần 'đặc điểm kỹ thuật' .

Bạn có thể sử dụng quá tải, nhưng nếu một phần lớn mã sẽ hoạt động cho bất kỳ loại nào, bạn có thể xem xét giải nén phần khác biệt thành một hàm riêng biệt và quá tải.

template <class T> 
void specific(const T&); 

void specific(const std::string&); 

template <class T> 
void something(const T& t) 
{ 
    //code that works on all types 
    specific(t); 
    //more code that works on all types 
} 
+0

Giải pháp đơn giản tuyệt vời, cảm ơn câu trả lời này! – avtomaton

0

Nếu bạn đang sử dụng C++ 11 hay muộn, std :: is_same thực hiện chính xác những gì bạn muốn:

template <typename T> 
constexpr bool IsFloat() { return std::is_same<T, float>::value; } 

template <typename T> 
void SomeMethodName() { 
    if (IsFloat<T>()) { 
    ... 
    } 
} 

http://en.cppreference.com/w/cpp/types/is_same

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