cast classes to common ancestor

Discussion in 'C++' started by deadguysfrom@gmail.com, Oct 7, 2007.

  1. Guest

    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
    , Oct 7, 2007
    #1
    1. Advertising

  2. Ian Collins Guest

    wrote:
    > 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;
    }

    --
    Ian Collins.
    Ian Collins, Oct 7, 2007
    #2
    1. Advertising

  3. * :
    > 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?
    Alf P. Steinbach, Oct 7, 2007
    #3
  4. Kai-Uwe Bux Guest

    Alf P. Steinbach wrote:

    > * :
    >> 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
    Kai-Uwe Bux, Oct 7, 2007
    #4
  5. * Kai-Uwe Bux:
    > Alf P. Steinbach wrote:
    >
    >> * :
    >>> 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?
    Alf P. Steinbach, Oct 7, 2007
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Denny
    Replies:
    1
    Views:
    759
  2. Ilmari Heikkinen
    Replies:
    0
    Views:
    95
    Ilmari Heikkinen
    Jan 17, 2005
  3. Amir Karger
    Replies:
    9
    Views:
    113
    Tassilo v. Parseval
    Dec 10, 2003
  4. John Reye
    Replies:
    28
    Views:
    1,331
    Tim Rentsch
    May 8, 2012
  5. Jason Mellone
    Replies:
    3
    Views:
    77
    Jurko Gospodnetić
    May 7, 2014
Loading...

Share This Page