Specialized C ++ template based on the presence / absence of a class member?

Consider the following:

struct A { typedef int foo; }; struct B {}; template<class T, bool has_foo = /* ??? */> struct C {}; 

I want to specialize C so that C <A> gets one specialization and C <B> gets another, based on the presence or absence of typename T :: foo. Is it possible to use type traits or some other template magic?

The problem is that everything I tried creates a compilation error when instantiating C <B> because B :: foo does not exist. But this is what I want to check!


Edit: I think ildjarn's answer is better, but I finally came up with the following C ++ 11 solution. Man is hacked, but at least short. :)

 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)> 
+8
c ++ templates typetraits template-specialization
source share
2 answers

Another approach (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 }; 
+6
source share

Something like this might help: 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 {}; 
+2
source share

All Articles