 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Jacek Generowicz Guest
|
Posted: Sat Apr 24, 2004 12:04 am Post subject: Dynamic cast offsets without an instance |
|
|
Brief summary of question:
Is it possible to calculate by how much a dynamic_cast adjusts a
pointer, without having an instance of the class(es) involved in the
cast ?
----------------------------------------------------------------------
More details:
Please consider the following code
#include <iostream>
struct Base {
int datum;
virtual ~Base(){}
};
struct Derived : public virtual Base {};
int main() {
Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b);
std::cout << (int)d - (int)b << std::endl;
return 0;
}
Output on gcc:
-4
Is there a way of persuading C++ compilers to calculate the quantity
which was calculated above, without having an instance of Derived (or
of Base) ?
(Note, there are 3 different tyes involved here, in general:
- static source type (SST)
- static destination type (SDT)
- dynamic type (DyT)
The last, could, in general be different from both of the previous
two; an instance of a class derived from Derived.)
---------------------------------------------------------------------
Background and motivation:
I am using some code which attempts to add some sort of introspection
to C++ (based on GCC_XML) and which allows interaction with C++
classes (and their instances) found in dynamic libraries for which the
system has constructed a "dictionary".
This system requires the aforementioned offsets in order to simulate
dynamic casting. It attempts to find them by default-constructing
instances of the classes, and performing a dynamic_cast ... but not
all classes have default constructors.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bill Weston Guest
|
Posted: Sun Apr 25, 2004 1:51 am Post subject: Re: Dynamic cast offsets without an instance |
|
|
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote
| Quote: | Brief summary of question:
Is it possible to calculate by how much a dynamic_cast adjusts a
pointer, without having an instance of the class(es) involved in the
cast ?
Sorry, don't know. Would be interested to find out if so, but expect |
to be disappointed.
[snip]
| Quote: | Background and motivation:
[snip]
This system requires the aforementioned offsets in order to simulate
dynamic casting. It attempts to find them by default-constructing
instances of the classes, and performing a dynamic_cast ... but not
all classes have default constructors.
|
As a tiny amelioration of this difficulty, you could wrap up the
default constructor as a default template, something like New<Foo>,
and specialise where there is no default ctor to whatever factory
function is necessary... something like (untested):
template<typename T>
struct New
{
T* tmp;
operator T*(){ return tmp; }
New(): tmp(new T()) {}
~New(){ delete tmp; } // depending on who is to own it
};
template<>
sctruct New<Foo>
{
// do whatever it takes!
}
Hoping someone posts a proper answer to your interesting question,
Bill Weston
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Carl Barron Guest
|
Posted: Sun Apr 25, 2004 10:45 pm Post subject: Re: Dynamic cast offsets without an instance |
|
|
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote:
| Quote: | Background and motivation:
I am using some code which attempts to add some sort of introspection
to C++ (based on GCC_XML) and which allows interaction with C++
classes (and their instances) found in dynamic libraries for which the
system has constructed a "dictionary".
This system requires the aforementioned offsets in order to simulate
dynamic casting. It attempts to find them by default-constructing
instances of the classes, and performing a dynamic_cast ... but not
all classes have default constructors.
Does your compiler optimize away the added space for a struct |
containing no addition data and possibly a default constructor?
Consider:
// Default setup class is default constructable so use the
// general template here:
template <class T> struct Wrapper:T{};
// for each class requiring a non default constructor are there fairly
// easy to construct areguments for this constructor?
// then template specialization like this:
struc non_default_constructor
{
non_default_constructor(int,const std::string &x);
}
template <> struct Wrapper<non_default_constructor>:T
{
Wrapper():T(0,""){}
};
// etc.
Will this work??
It is possible to use Loki to generate the code to generate the
results fairly easily using a TypeList of types derived from a base
class and that base class. [details omitted but doable if this works.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Paul D. DeRocco Guest
|
Posted: Sun Apr 25, 2004 11:17 pm Post subject: Re: Dynamic cast offsets without an instance |
|
|
| Quote: | "Jacek Generowicz" <jacek.generowicz (AT) cern (DOT) ch> wrote
Brief summary of question:
Is it possible to calculate by how much a dynamic_cast adjusts a
pointer, without having an instance of the class(es) involved in the
cast ?
|
No. Without an actual instance, you can't do anything fancier than you can
with static_cast.
--
Ciao, Paul D. DeRocco
Paul mailto:pderocco (AT) ix (DOT) netcom.com
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Michiel Salters Guest
|
Posted: Mon Apr 26, 2004 2:23 pm Post subject: Re: Dynamic cast offsets without an instance |
|
|
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote
| Quote: | Brief summary of question:
Is it possible to calculate by how much a dynamic_cast adjusts a
pointer, without having an instance of the class(es) involved in the
cast ?
|
No:
struct A { virtual ~A() {} };
struct B : public A { };
struct C : public A { };
struct D : public B, public C { };
The adjustment from A* to D* depends on which of the two A bases
the A* points to, which in general is a runtime property.
Regards,
Michiel Salters
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jacek Generowicz Guest
|
Posted: Tue Apr 27, 2004 10:50 am Post subject: Re: Dynamic cast offsets without an instance |
|
|
[email]Michiel.Salters (AT) logicacmg (DOT) com[/email] (Michiel Salters) writes:
| Quote: | Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote
Brief summary of question:
Is it possible to calculate by how much a dynamic_cast adjusts a
pointer, without having an instance of the class(es) involved in the
cast ?
No:
struct A { virtual ~A() {} };
struct B : public A { };
struct C : public A { };
struct D : public B, public C { };
The adjustment from A* to D* depends on which of the two A bases
the A* points to, which in general is a runtime property.
|
Indeed. I didn't really mean "compiler", I meant "compiler and
runtime" or maybe "implementation". IOW, I'm trying to avoid, if at
all possible, having to feed in implementation dependent knowledge
about the objects' layouts; I would like the implementation to give me
this information.
Perhaps a slightly different approach might work ...
Is there some run-time programmatic way to access the underlying
functionality of dynamic_cast? a means of specifying, at run-time, the
type to which the cast should be performed. If it were somehow
possible to specify the target type of the cast by passing a typeinfo
pointer[*], rather than with a template argument, this would probably be
quite satisfactory. Even if it is an implementation dependent trick,
it seems much cleaner and more manageable than implementation
dependent layout knowledge.
[*] The static source type would also have to be communicated by
typeinfo, I suppose.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
David Baraff Guest
|
Posted: Wed Apr 28, 2004 9:34 am Post subject: Re: Dynamic cast offsets without an instance |
|
|
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote in message news:
| Quote: | Is there some run-time programmatic way to access the underlying
functionality of dynamic_cast? a means of specifying, at run-time, the
type to which the cast should be performed.
|
In g++ (certainly in 3.3, and going back for a few releases) the
functionality you want is described in the cxxabi.h header file. In
particular, the RTTI datastructures give you access to the inheritance
graph, and the offsets are also encoded. You'll probably have to read
the file a bunch of times before it makes sense, but you can
essentially say "take this void*, pretend it is of type T1, cast it to
a void* that would point to a T2." (Where you communicate T1 and T2
by passing type_info's.)
Of course, the drawback is that this technique limits you to compilers
that support this particular ABI (which is hopefully soon going to be
many compilers). For example, I wouldn't hold my breath waiting for
this to work under the Microsoft C++ compiler...
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jacek Generowicz Guest
|
Posted: Wed Apr 28, 2004 7:41 pm Post subject: Re: Dynamic cast offsets without an instance |
|
|
[email]deb (AT) pixar (DOT) com[/email] (David Baraff) writes:
| Quote: | Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote in message news:
Is there some run-time programmatic way to access the underlying
functionality of dynamic_cast? a means of specifying, at run-time, the
type to which the cast should be performed.
In g++ (certainly in 3.3, and going back for a few releases) the
functionality you want is described in the cxxabi.h header file.
|
Yes, this seems to do the trick ... for example:
#include <iostream>
#include <cxxabi.h>
struct Base {
int datum;
virtual ~Base(){}
};
struct Derived : public virtual Base {};
int main() {
// The usual static approach
Base* b = new Derived;
Derived* d = dynamic_cast<Derived*>(b);
std::cout << (int)d - (int)b << std::endl;
// The runtime-via-typeinfo approach
void* vb = (void*) b;
__cxxabiv1::__class_type_info* Bti = (__cxxabiv1::__class_type_info*)(&typeid(Base));
__cxxabiv1::__class_type_info* Dti = (__cxxabiv1::__class_type_info*)(&typeid(Derived));
void* vd = __cxxabiv1::__dynamic_cast(vb, Bti, Dti, -1);
std::cout << (int)vd - (int)vb << std::endl;
return 0;
}
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jacek Generowicz Guest
|
Posted: Wed Apr 28, 2004 7:45 pm Post subject: Re: Dynamic cast offsets without an instance |
|
|
[email]deb (AT) pixar (DOT) com[/email] (David Baraff) writes:
| Quote: | In g++ (certainly in 3.3, and going back for a few releases) the
functionality you want is described in the cxxabi.h header file.
|
[...]
| Quote: | you can essentially say "take this void*, pretend it is of type T1,
cast it to a void* that would point to a T2." (Where you
communicate T1 and T2 by passing type_info's.)
|
Perfect, that's exactly the sort of thing I was thinking of. I'll dig
around in there. Thanks.
| Quote: | Of course, the drawback is that this technique limits you to compilers
that support this particular ABI (which is hopefully soon going to be
many compilers). For example, I wouldn't hold my breath waiting for
this to work under the Microsoft C++ compiler...
|
Indeed, but if there is no more portable alternative, then so be it.
Anyone know where to look for this sort of thing in MSVC ?
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Bill Weston Guest
|
Posted: Thu Apr 29, 2004 9:27 pm Post subject: Re: Dynamic cast offsets without an instance |
|
|
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote
| Quote: | deb (AT) pixar (DOT) com (David Baraff) writes:
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> wrote in message news:
Is there some run-time programmatic way to access the underlying
functionality of dynamic_cast? a means of specifying, at run-time, the
type to which the cast should be performed.
In g++ (certainly in 3.3, and going back for a few releases) the
functionality you want is described in the cxxabi.h header file.
Yes, this seems to do the trick ... for example:
#include <iostream
#include
struct Base {
int datum;
virtual ~Base(){}
};
struct Derived : public virtual Base {};
int main() {
// The usual static approach
Base* b = new Derived;
Derived* d = dynamic_cast
std::cout << (int)d - (int)b << std::endl;
// The runtime-via-typeinfo approach
void* vb = (void*) b;
__cxxabiv1::__class_type_info* Bti = (__cxxabiv1::__class_type_info*)(&typeid(Base));
__cxxabiv1::__class_type_info* Dti = (__cxxabiv1::__class_type_info*)(&typeid(Derived));
void* vd = __cxxabiv1::__dynamic_cast(vb, Bti, Dti, -1);
std::cout << (int)vd - (int)vb << std::endl;
return 0;
}
|
THis is cool! It makes multiple dispatch possible naturally within
the laguage, albeit with explicit registration of dispatchees.
Hmmmm. Multiply dispatching observer patterns maybe, since one needs
to register observers anyway.
Cheers,
Bill Weston
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Jacek Generowicz Guest
|
Posted: Fri Apr 30, 2004 11:20 am Post subject: Re: Dynamic cast offsets without an instance |
|
|
Jacek Generowicz <jacek.generowicz (AT) cern (DOT) ch> writes:
| Quote: | __cxxabiv1::__class_type_info* Bti = (__cxxabiv1::__class_type_info*)(&typeid(Base));
__cxxabiv1::__class_type_info* Dti = (__cxxabiv1::__class_type_info*)(&typeid(Derived));
void* vd = __cxxabiv1::__dynamic_cast(vb, Bti, Dti, -1);
|
You can even replace "__cxxabiv1::" by "abi::" in the above.
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|