* Kai-Uwe Bux:
Since it sounded like a nice template exercise, I just tried to do that,
i.e., I tried to whip up a template
template < typename A, typename B >
class have_common_base {
// some SFINAE magic
public:
static bool const value =
// some more magic
};
so that have_common_base<A,B>::value would be true if and only if A and B
are derived from some common base class.
I failed, and your hint didn't quite cut it for me :-(
How would you do it?
Uh, that was stupid of me. Doing what you tried (and what I literally
wrote) requires first finding the common ancestor class... Catch 22.
Fix:
"You can check whether the classes /have/ a given common ancestor by
using static_cast, possibly combined with SFINAE."
Like e.g.
<code>
#include <iostream>
#include <ostream>
typedef char Nope;
struct Yep{ char x[2]; };
template< typename T >
Nope matches( ... );
template< typename T >
Yep matches( T* );
enum { yepSize = sizeof( Yep ), nopeSize = sizeof( Nope ) };
template< typename Derived, typename Base >
bool hasBase(){ return sizeof( matches<Base>( static_cast<Derived*>(0) )
) == yepSize; }
template< typename A, typename B, typename Base >
bool haveCommonBase() { return hasBase<A, Base>() && hasBase<B, Base>(); };
struct Base {};
struct A: Base {};
struct B: Base {};
struct X {};
struct Y {};
int main()
{
using namespace std;
cout << haveCommonBase<A, B, Base>() << endl;
cout << haveCommonBase<X, Y, Base>() << endl;
}
</code>
Here 'hasBase' can yield false positives, for Base = void. Instead one
may use the more elaborate Boost checks.
Cheers,
- Alf (impreftc, and rowing energetically ;-) )