cast classes to common ancestor

D

deadguysfrom

Ive got two classes in the same class hierarchy, and I want to find
their common ancestor. Any idea how to do this?

class A {};
class B : public A {};
class C : public B {};
class D : public B {};

I have pointers to C and D, I want pointers to B.

thanks
 
I

Ian Collins

Ive got two classes in the same class hierarchy, and I want to find
their common ancestor. Any idea how to do this?

class A {};
class B : public A {};
class C : public B {};
class D : public B {};

I have pointers to C and D, I want pointers to B.
int main()
{
D* d = new D;

B* b = d;
}
 
A

Alf P. Steinbach

* (e-mail address removed):
Ive got two classes in the same class hierarchy, and I want to find
their common ancestor. Any idea how to do this?

class A {};
class B : public A {};
class C : public B {};
class D : public B {};

I have pointers to C and D, I want pointers to B.

See the reply by Ian Collins else-thread.

If your enquiry is of a more academic, theoretical nature:

You can check whether the classes /have/ a common ancestor by using
static_cast, possibly combined with SFINAE.

You can go the opposite way, finding a pointer to the complete object
(of the most derived class), by using dynamic_cast<void*>, provided the
pointer you have is a pointer to an object of polymorphic class. This
is sometimes useful, e.g. for hashing. But it doesn't tell you what the
most derived class is, except you can get a run-time description.

You can not enumerate the class hierarchy by means of only language and
standard library functionality.

Cheers, & hth.,

- Alf
 
K

Kai-Uwe Bux

Alf said:
* (e-mail address removed):

See the reply by Ian Collins else-thread.

If your enquiry is of a more academic, theoretical nature:

You can check whether the classes /have/ a common ancestor by using
static_cast, possibly combined with SFINAE.

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?

[snip]


Best

Kai-Uwe Bux
 
A

Alf P. Steinbach

* 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 ;-) )
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,820
Latest member
GilbertoA5

Latest Threads

Top