Discussion:
cannot dynamic_cast 't' (of type 'void*') to type 'struct mom::object*' (source is not a pointer to class)
(too old to reply)
verec
2005-08-07 13:09:22 UTC
Permalink
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::object*' (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
Alipha
2005-08-07 17:28:24 UTC
Permalink
Post by verec
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).
Post by verec
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 ...
cannot dynamic_cast 't' (of type 'void*') to type
'struct mom::object*' (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?
Post by verec
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
Post by verec
}
// ...
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.
Post by verec
Many thanks
--
JFB
Alf P. Steinbach
2005-08-07 17:39:38 UTC
Permalink
Post by Alipha
Post by verec
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?
verec
2005-08-07 19:17:26 UTC
Permalink
Post by Alipha
Post by verec
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...
Post by Alipha
Post by verec
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.
Post by Alipha
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
benben
2005-08-08 10:46:18 UTC
Permalink
Post by verec
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
verec
2005-08-15 23:02:25 UTC
Permalink
Post by benben
Post by verec
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

Loading...