| cast classes to common ancestor [message #17371] |
Sat, 06 October 2007 22:04  |
deadguysfrom Messages: 1 Registered: October 2007 |
Junior Member |
|
|
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
|
|
|
|
| Re: cast classes to common ancestor [message #17373 is a reply to message #17371 ] |
Sat, 06 October 2007 22:44   |
alfps Messages: 315 Registered: July 2007 |
Senior Member |
|
|
* deadguysfrom@gmail.com:
> 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
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
|
|
|
| Re: cast classes to common ancestor [message #17374 is a reply to message #17373 ] |
Sat, 06 October 2007 23:15   |
Kai-Uwe Bux Messages: 138 Registered: July 2007 |
Senior Member |
|
|
Alf P. Steinbach wrote:
> * deadguysfrom@gmail.com:
>> 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.
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
|
|
|
| Re: cast classes to common ancestor [message #17375 is a reply to message #17374 ] |
Sun, 07 October 2007 00:13  |
alfps Messages: 315 Registered: July 2007 |
Senior Member |
|
|
* Kai-Uwe Bux:
> Alf P. Steinbach wrote:
>
>> * deadguysfrom@gmail.com:
>>> 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.
>
> 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 ;-) )
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
|
|
|