2012-10-27 36 views
10

Hiện nay tôi có hai chức năng:Phát hiện xem loại có phải là std :: tuple không?

template<typename Type> bool f(Type* x); 
template<typename... List> bool f(std::tuple<List...>* x); 

Có cách nào để hợp nhất hai chức năng này với một tham số mẫu bổ sung mà chỉ ra cho dù các loại trôi qua là một tuple?

template<typename Type, bool IsTuple = /* SOMETHING */> bool f(Type* x); 

Trả lời

10

Chắc chắn, sử dụng is_specialization_of (liên kết thực hiện và cố định từ here):

template<typename Type, bool IsTuple = is_specialization_of<Type, std::tuple>::value> 
bool f(Type* x); 

Câu hỏi là, tuy nhiên, bạn có thực sự muốn điều đó? Thông thường, nếu bạn cần biết nếu một kiểu là một bộ tuple, bạn cần xử lý đặc biệt cho các bộ dữ liệu và thường phải làm với các đối số mẫu của nó. Như vậy, bạn có thể muốn dính vào phiên bản quá tải của bạn.

Edit: Vì bạn nói bạn chỉ cần một phần nhỏ chuyên, tôi khuyên bạn nên quá tải nhưng chỉ cho một phần đặc biệt nhỏ:

template<class T> 
bool f(T* x){ 
    // common parts... 
    f_special_part(x); 
    // common parts... 
} 

với

template<class T> 
void f_special_part(T* x){ /* general case */ } 

template<class... Args> 
void f_special_part(std::tuple<Args...>* x){ /* special tuple case */ } 
+0

Trong thời gian bình thường này có thể là nguy hiểm và một chuyên môn hóa sẽ thích hợp hơn. Nhưng hàm này là một hàm lớn, và chỉ có một 'if' nhỏ bên trong thay đổi kiểu tuple hay không. – Vincent

+0

Sử dụng tham số mẫu phụ cũng có nghĩa là có thể gọi rõ ràng 'f , false> 'hoặc' f ', có thể tránh được bằng cách kiểm tra' is_specialization_of' trong phần hàm. – hvd

+0

@Vincent: Sau đó, tôi thực sự khuyên bạn nên gửi thẻ thay vì thời gian chạy 'if'. :) – Xeo

5

Bạn chỉ có thể có của bạn chức năng trì hoãn chức năng khác:

template<typename Type,bool IsTuple> bool f(Type *x); 

template<typename Type> 
inline bool f(Type* x) { return f<Type,false>(x); } 

template<typename... List> 
inline bool f(std::tuple<List...>* x) { return f<std::tuple<List...>,true>(x); } 
1

Với C++ 17, đây là một giải pháp khá đơn giản sử dụng if constexpr

template <typename> struct is_tuple: std::false_type {}; 

template <typename ...T> struct is_tuple<std::tuple<T...>>: std::true_type {}; 

Sau đó, bạn có thể làm điều gì đó như:

template<typename Type> bool f(Type* x) { 
    if constexpr (is_tuple<Type>::value) { 
     std::cout << "A tuple!!\n"; 
     return true; 
    } 

    std::cout << "Not a tuple\n"; 
    return false; 
} 

Một thử nghiệm để đảm bảo nó làm việc:

f(&some_tuple); 
f(&some_object); 

Đầu ra:

Tuple !!
Không phải là một tuple


Giải pháp thực hiện trong một phần từ một answer tìm thấy ở đây: How to know if a type is a specialization of std::vector?

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