views:

656

answers:

1

Using SFINAE, i can detect wether a given class has a certain member function. But what if i want to test for inherited member functions?

The following does not work in VC8 and GCC4 (i.e. detects that A has a member function foo(), but not that B inherits one):

#include <iostream>

template<typename T, typename Sig>                                 
struct has_foo {                     
    template <typename U, U> struct type_check;
    template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1];
    template <typename  > static char (& chk(...))[2]; 
    static bool const value = (sizeof(chk<T>(0)) == 1);
};

struct A {
    void foo();
};

struct B : A {};

int main()
{
    using namespace std;
    cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true
    cout << boolalpha << has_foo<B, void (B::*)()>::value << endl; // false
}

So, is there a way to test for inherited member functions?

+5  A: 

Take a look at this thread:

http://lists.boost.org/boost-users/2009/01/44538.php

Derived from the code linked to in that discussion:

#include <iostream>

template <typename Type> 
class has_foo
{ 
   class yes { char m;}; 
   class no { yes m[2];}; 
   struct BaseMixin 
   { 
     void foo(){} 
   }; 
   struct Base : public Type, public BaseMixin {}; 
   template <typename T, T t>  class Helper{}; 
   template <typename U> 
   static no deduce(U*, Helper<void (BaseMixin::*)(), &U::foo>* = 0); 
   static yes deduce(...); 
public: 
   static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0))); 
}; 

struct A {
    void foo();
};

struct B : A {};

struct C {};

int main()
{
    using namespace std;
    cout << boolalpha << has_foo<A>::result << endl;
    cout << boolalpha << has_foo<B>::result << endl;
    cout << boolalpha << has_foo<C>::result;
}

Result:

true
true
false
joshperry
Nice, thank you.
Georg Fritzsche
It's the one shown here: http://stackoverflow.com/questions/1005476/how-to-detect-whether-there-is-a-specific-member-variable-in-class/1007175#1007175 and explained here: http://cplusplus.co.il/2009/09/11/substitution-failure-is-not-an-error-1/ . Keep in mind it will signal that there is a member of that name even if the member isn't a function or the function has some other signature, so it's doing something different. It needs the other codes shown in the usenet discussion to do further checks.
Johannes Schaub - litb
Didn't notice the missing type check, good point. You probably mean using `is_call_possible<>` from here http://groups.google.com/group/comp.lang.c++.moderated/msg/e5fbc9305539f699 ? Looks interesting, will have to test later.
Georg Fritzsche