Is it possible to check if a member function is defined for a class even if the member is inherited from an unknown base class

c++, sfinae

Solution

Unfortunately it wouldn't be possible at least in C++03 and I doubt in C++11 also.

Few important points:

- The proposed SFINAE works only if the method is `public`

- Even if the SFINAE would have worked for base methods, the point (1) applies; because for `private` and `protected` inheritance the SFINAE may end up useless

- Assuming you may want to deal only with `public` method/inheritance, the code `HasFoo::test<>` can be enhanced for taking multiple parameters where a base class also can be passed; `std::is_base_of<>` can be used for further validation of the base/derived relationship; then apply the same logic for base class also

Problem

I found similar questions and answers like this one. However, as I tried out, this SFINAE tests only succeeded if the tested member is directly defined in the class being tested. For example the following, class `B`, `D1` print `HAS` while the other two print `NOT HAS`. Is there a way to determine that if a class has a member, whether it is defined by itself, or a base class, and the name of the base class is not known in this case. The motivation is that I want to write a generic function that will call a certain method if it exists (from base or not, the type of the parameter is generic, leave along the type of its possible base). ``` #include <iostream> class HasFoo { public : typedef char Small; typedef struct {char; char;} Large; template <typename C, void (C::*) ()> class SFINAE {}; template <typename C> static Small test (SFINAE<C, &C::foo> *) { std::cout << "HAS" << std::endl; } template <typename C> static Large test (...) { std::cout << "NOT HAS" << std::endl; } }; class B { public : void foo () {} }; class D1 : public B { public : void foo () {} // overide }; class D2 : public B { public : using B::foo; }; class D3 : public B {}; int main () { HasFoo::test<B>(0); HasFoo::test<D1>(0); HasFoo::test<D2>(0); HasFoo::test<D3>(0); } ```

Original source

Related problems