2012-04-27 37 views
8

xem xét như sau:Chuyên mẫu C++ dựa trên sự hiện diện/vắng mặt của một thành viên lớp học?

struct A { 
    typedef int foo; 
}; 

struct B {}; 

template<class T, bool has_foo = /* ??? */> 
struct C {}; 

Tôi muốn chuyên C để C < Một > được một chuyên môn hóa và C <B> được người kia, dựa trên sự hiện diện hay vắng mặt của typename T :: foo. Điều này có thể sử dụng các đặc tính kiểu hoặc một số mẫu ma thuật khác không?

Vấn đề là mọi thứ tôi đã thử tạo ra lỗi biên dịch khi khởi tạo C <B> vì B :: foo không tồn tại. Nhưng đó là những gì tôi muốn thử nghiệm!


Chỉnh sửa: Tôi nghĩ câu trả lời của ildjarn tốt hơn, nhưng cuối cùng tôi đã đưa ra giải pháp C++ 11 sau. Người đàn ông là nó hacky, nhưng ít nhất là nó ngắn. :)

template<class T> 
constexpr typename T::foo* has_foo(T*) { 
    return (typename T::foo*) 1; 
} 
constexpr bool has_foo(...) { 
    return false; 
} 
template<class T, bool has_foo = (bool) has_foo((T*)0)> 
+0

Bạn nên nói bạn đã quan tâm đến một giải pháp C++ 11. : -] Bạn không sao, nhưng quá tải 'has_foo (T *)' có thể được cải thiện bằng cách trả về 'bool' và sử dụng biểu thức SFINAE, vì vậy không cần phải cast ở callite. – ildjarn

+0

'(T *) 0)' phải là 'declval ()', có thể – Lol4t0

Trả lời

6

Một (C++ 03) cách tiếp cận:

template<typename T> 
struct has_foo 
{ 
private: 
    typedef char no; 
    struct yes { no m[2]; }; 

    static T* make(); 
    template<typename U> 
    static yes check(U*, typename U::foo* = 0); 
    static no check(...); 

public: 
    static bool const value = sizeof(check(make())) == sizeof(yes); 
}; 

struct A 
{ 
    typedef int foo; 
}; 

struct B { }; 

template<typename T, bool HasFooB = has_foo<T>::value> 
struct C 
{ 
    // T has foo 
}; 

template<typename T> 
struct C<T, false> 
{ 
    // T has no foo 
}; 
2

Điều gì đó có thể giúp ích: has_member.

typedef char (&no_tag)[1]; 
typedef char (&yes_tag)[2]; 

template< typename T > no_tag has_member_foo_helper(...); 

template< typename T > yes_tag has_member_foo_helper(int, void (T::*)() = &T::foo); 

template< typename T > struct has_member_foo { 
    BOOST_STATIC_CONSTANT(bool 
     , value = sizeof(has_member_foo_helper<T>(0)) == sizeof(yes_tag) 
     ); }; 

template<class T, bool has_foo = has_member_foo<T>::value> 
struct C {}; 
Các vấn đề liên quan