cannot dynamic_cast 't' (of type 'void*') to type 'struct mom::object*' (source is not a pointer to

Discussion in 'C++' started by verec, Aug 7, 2005.

  1. verec

    verec Guest

    I just do not understand this error.
    Am I misusing dynamic_cast ?

    What I want to do is to have a single template construct
    (with no optional argument) so that it works for whatever
    T I want to use it with. Now, if that T happens to be some
    subclass of a known base class (object, in this case), I
    want to perform some extra stuff ...

    I've read Faq#35, and the most natural solution would have
    been to write the function as a non static envelope member
    parameterized on T, but the reason the code is "out-line" is
    because of a circular dependency that would be introduced
    between object & envelope if I was to let envelope.hpp know
    about the innards of object.hpp.

    I solved this by using a "free standing", non templatized regular
    function, whose definition, inside envelope.cpp is now allowed
    to include object.hpp ...

    /Users/verec/Tools/trunk/Style/tests/build/mom/../../../src/common/mom/envelope.cpp:68:
    error:

    cannot dynamic_cast 't' (of type 'void*') to type
    'struct mom::eek:bject*' (source is not a pointer to class)

    file envelope.hpp

    namespace mom {
    // ...
    void construct(void * t) ; // <-- decl

    template <typename T> struct envelope {


    // ...

    static void * cast(T * t) {

    return dynamic_cast<void *>(t) ;

    }

    // ...

    envelope(T * q = 0) : body(q) {
    // ...
    construct(cast(body)) ;

    }
    } ;
    }

    file envelope.cpp

    #include "mom/envelope.hpp"
    #include "mom/object.hpp"

    namespace mom {

    // ...
    void
    construct(void * t) {
    object * o = dynamic_cast<object *>(t) ; // <-- defn: where
    GCC 4.0 chokes.
    if (o) {
    o->construct() ;
    }
    }
    }

    for completeness ...
    file opbject.hpp

    namespace mom {
    struct object {
    object() {}

    virtual
    ~object() {}

    virtual void
    construct() {}
    // ...
    } ;
    }

    Any idea what I'm doing wrong?

    Many thanks
    --
    JFB
     
    verec, Aug 7, 2005
    #1
    1. Advertising

  2. verec

    Alipha Guest

    verec wrote:
    > I just do not understand this error.
    > Am I misusing dynamic_cast ?


    yes. you can't cast from void* because the compiler can't know what
    type the object really is. you can only cast from polymorphic types (in
    which case, the compiler typically looks at the v-table pointer to
    determine what type the object really is).


    > What I want to do is to have a single template construct
    > (with no optional argument) so that it works for whatever
    > T I want to use it with. Now, if that T happens to be some
    > subclass of a known base class (object, in this case), I
    > want to perform some extra stuff ...
    >
    > I've read Faq#35, and the most natural solution would have
    > been to write the function as a non static envelope member
    > parameterized on T, but the reason the code is "out-line" is
    > because of a circular dependency that would be introduced
    > between object & envelope if I was to let envelope.hpp know
    > about the innards of object.hpp.
    >
    > I solved this by using a "free standing", non templatized regular
    > function, whose definition, inside envelope.cpp is now allowed
    > to include object.hpp ...
    >
    > /Users/verec/Tools/trunk/Style/tests/build/mom/../../../src/common/mom/envelope.cpp:68:
    > error:
    >
    > cannot dynamic_cast 't' (of type 'void*') to type
    > 'struct mom::eek:bject*' (source is not a pointer to class)
    >
    > file envelope.hpp
    >
    > namespace mom {
    > // ...
    > void construct(void * t) ; // <-- decl


    void construct(void * t);
    void construct(object * t);

    problem solved?

    >
    > template <typename T> struct envelope {
    >
    >
    > // ...
    >
    > static void * cast(T * t) {
    >
    > return dynamic_cast<void *>(t) ;


    the cast is completely unnecessary, T* converts to void* implicitly,
    where T is not a function or member function type. of course, if you
    convert to void*, you lose all type info, which probably isn't a good
    thing.

    you might want to consider boost::any, however that probably won't help
    with your overall design. www.boost.org

    > }
    >
    > // ...
    >
    > envelope(T * q = 0) : body(q) {
    > // ...
    > construct(cast(body)) ;
    >
    > }
    > } ;
    > }
    >
    > file envelope.cpp
    >
    > #include "mom/envelope.hpp"
    > #include "mom/object.hpp"
    >
    > namespace mom {
    >
    > // ...
    > void
    > construct(void * t) {
    > object * o = dynamic_cast<object *>(t) ; // <-- defn: where
    > GCC 4.0 chokes.
    > if (o) {
    > o->construct() ;
    > }
    > }
    > }
    >
    > for completeness ...
    > file opbject.hpp
    >
    > namespace mom {
    > struct object {
    > object() {}
    >
    > virtual
    > ~object() {}
    >
    > virtual void
    > construct() {}
    > // ...
    > } ;
    > }
    >
    > Any idea what I'm doing wrong?


    quite frankly, any program design which includes such an incredibly
    generic object base class usually smells of a bad design. you can't do
    anything with this object other than construct or destroy it. you'd
    have to cast to a more specific derived class type to do anything
    useful with it, which trying to figure out what derived class to cast
    to is generally a "fun" exercise. C++ doesn't have an object base class
    for a reason.
    >
    > Many thanks
    > --
    > JFB
     
    Alipha, Aug 7, 2005
    #2
    1. Advertising

  3. * Alipha:
    > >
    > > static void * cast(T * t) {
    > >
    > > return dynamic_cast<void *>(t) ;

    >
    > the cast is completely unnecessary, T* converts to void* implicitly,
    > where T is not a function or member function type.


    Given the rest of the code one might think so, but this is a very special
    case: a dynamic cast to void* gives a pointer to the most derived object.
    E.g., T could here be an interface that t, an object instantiated from C,
    implements. The dynamic cast gives a pointer to the C object. The problem
    is doing something useful with that void* pointer. There is no dynamic cast
    back again, so except for comparing pointer values (which is the only
    portable usage I know of) the client code needs to know the type C.

    --
    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, Aug 7, 2005
    #3
  4. verec

    verec Guest

    On 2005-08-07 18:28:24 +0100, "Alipha" <> said:

    > verec wrote:
    >> I just do not understand this error.
    >> Am I misusing dynamic_cast ?

    >
    > yes. you can't cast from void* because the compiler can't know what
    > type the object really is. you can only cast from polymorphic types (in
    > which case, the compiler typically looks at the v-table pointer to
    > determine what type the object really is).


    Thanks. So the cast to void * is one way street, even though *I am*
    telling the compiler what I expect it to cast to: why is dynamic_cast
    supposed to return 0 or even throw bad_cast if not for the possibility
    I may have lied to the compiler... Well, I'l learn to live with that
    I suppose...

    On 2005-08-07 18:39:38 +0100, (Alf P. Steinbach) said:

    >> the cast is completely unnecessary, T* converts to void* implicitly,
    >> where T is not a function or member function type.

    >
    > Given the rest of the code one might think so, but this is a very special
    > case: a dynamic cast to void* gives a pointer to the most derived object.
    > E.g., T could here be an interface that t, an object instantiated from C,
    > implements. The dynamic cast gives a pointer to the C object. The problem
    > is doing something useful with that void* pointer.


    Store them in a map, no matter what branch of the derivation was used.

    > There is no dynamic cast back again


    This was the most unexpected event for today :-( I'll have to rethink
    how I'm going to cope with that.

    Many thanks to both.
    --
    JFB
     
    verec, Aug 7, 2005
    #4
  5. verec

    benben Guest

    > Thanks. So the cast to void * is one way street, even though *I am*
    > telling the compiler what I expect it to cast to: why is dynamic_cast
    > supposed to return 0 or even throw bad_cast if not for the possibility
    > I may have lied to the compiler... Well, I'l learn to live with that
    > I suppose...
    >


    If you are so confident you can use reinterpret_cast. I wouldn't...

    Ben
     
    benben, Aug 8, 2005
    #5
  6. verec

    verec Guest

    On 2005-08-08 11:46:18 +0100, "benben" <> said:

    >> Thanks. So the cast to void * is one way street, even though *I am*
    >> telling the compiler what I expect it to cast to: why is dynamic_cast
    >> supposed to return 0 or even throw bad_cast if not for the possibility
    >> I may have lied to the compiler... Well, I'l learn to live with that
    >> I suppose...

    > If you are so confident you can use reinterpret_cast. I wouldn't...


    Many thanks for the idea. It turns out that I was just confused about
    the need to:
    - forward declare to avoid circular dependencies
    - have every single template definition inside a header file so that
    the compiler could instantiate it as and when.

    The code now reads:

    file envelope.hpp

    namespace mom {
    // ...
    struct object ; // forward decl
    void construct_if(object * o) ;

    // ...
    template <typename T> struct envelope {
    // ...
    envelope(T * q = 0) : body(q) {
    // ...
    construct_if(dynamic_cast<object *>(body)) ;

    }
    } ;
    }

    file envelope.cpp

    #include "mom/envelope.hpp"
    #include "mom/object.hpp"

    namespace mom {

    // ...
    void
    construct_if(object * o) {
    if (o) {
    o->construct() ;
    }
    }
    }

    And I'm happy :)

    Many Thanks
    --
    JFB
     
    verec, Aug 16, 2005
    #6
    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. Ollej Reemt
    Replies:
    7
    Views:
    567
    Jack Klein
    Apr 22, 2005
  2. Stig Brautaset

    `void **' revisited: void *pop(void **root)

    Stig Brautaset, Oct 25, 2003, in forum: C Programming
    Replies:
    15
    Views:
    812
    The Real OS/2 Guy
    Oct 28, 2003
  3. William Payne

    If a cast from void* to a struct type pointer fails

    William Payne, Feb 13, 2004, in forum: C Programming
    Replies:
    4
    Views:
    898
    Christopher Benson-Manica
    Feb 17, 2004
  4. Replies:
    5
    Views:
    850
    S.Tobias
    Jul 22, 2005
  5. Replies:
    1
    Views:
    418
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page