2012-04-27 7 views
8

は、次のことを考えてみましょう:クラスメンバの有無に基づくC++テンプレートの特化?

struct A { 
    typedef int foo; 
}; 

struct B {}; 

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

私はC < >一つ専門を取得し、C <B>は、型名Tの有無に基づいて、他を取得します:: fooのようにCを専門としたいです。これは、タイプ形質やその他のテンプレートマジックを使用して可能ですか?

問題は、B :: fooが存在しないため、C <B>をインスタンス化するときに、試したすべてがコンパイルエラーを生成するということです。しかし、それは私がテストしたいものです!


編集: 私はildjarnの答えは良いですが、私は最終的には、以下のC++ 11解決策を考え出したと思います。男はそれはハッキーですが、少なくともそれは短いです。 :)

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

あなたがC++ 11溶液中で興味を持っていたと述べている必要があります。 :あなたのものは大丈夫ですが、 'bool'を返しSFINAEという式を使うことで' has_foo(T *) 'オーバーロードが改善される可能性があるので、コールサイトでキャストする必要はありません。 – ildjarn

+0

'(T *)0)'は 'declake ()'でなければなりません – Lol4t0

答えて

6

別(C++ 03)アプローチ:

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

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 {}; 
関連する問題