I know that I can create method pointers, and I know that they are generally different than function pointers. Converting between them is not allowed. Method pointers can contain lots of data about how to adjust this
pointer and so on.
I would like to know how to get actual address of code that is executing given method. This address will not be deferenced in any way, but will be used as identifier of type to which given method belongs - something a bit like RTTI, with advantage of being insensitive to library-boundaries, as this code is available in only one unit usually.
EDIT:
Why i don't add some getType()
method returning object's type?
Because I want to be able to use in this manner not only classes created by me. What I am trying to do is basically my implementation ofvariant
class, that would accept basically everything, provided specialization of void* getVariantId() for given type exists.
So then i could write:
template <typename T>
class getTypeId{
};
class foo{
public:
void bar();
};
// getTypeId declared but not defined for generic type T earlier...
template <>
class getTypeId<foo>{
static void* get<foo>(){
return &foo::bar;
}
};
void doSomething(myVariant var);
int main(int argc, char* argv[]){
foo f;
myVariant var = myVariant::fromType<foo*>(&f);
doSomething(f);
}
void doSomething(myVariant var){
foo* f = var.toType<foo*>(); // Returns foo object from main
int* i = var.toType<int*>(); // returns null, as var is not int* in my example.
}
The idea is that fromType
is using getTypeId
to obtain type's representing value, and stronig it along with object's pointer casted to void*
. toType
on the other hand is comparing value got from `getTypeId::get and one stored in object - if it matches then internally kept object pointer is reinterpreted back to original type and returned.
Beauty of this solution is, that even if there is some shared library X, that define type x, then libraries Y and Z, that separately use library X would agree on type x being the same (eg. in case variant create in Y is passed to Z), cause address on X::method remains the same. As creator of Y or Z library (but NOT X!!!), I don't need to ensure X lib has RTTI enabled or even is aware of myVariant existence, yet type x is still fully myVariant compatible.
EDIT2:
I see by now that there is no implementation-independent way to get this done. However I think that this is quirk of not-usually-needed, and therefore not-existing feature, rather than feature that is impossible to create. I think I still haven't made it clear what I wanted to acheive and how I was plannig to do so. So:
By libraries I mean here shared libraries (.dll, .so and so on).
Every method that is not pure virtual (means every method that is defined) must have implementation. This implementation behaves as a function that accepts one additional parameter this
- virtual functions are different only on caller side. Let's take class X and it's method X::foo
as an example. This method is bound only to X type, even if type Y inherits it, this method remains X::foo
and therefore it is enought to identify type X
. Overriding virtual method or covering method in child class Xchild
is de-facto defining new method Xchild::foo with new address. Then you might use Xchild::foo
to represent Xchild
, but not X
.
If type X (all it's methods to be accurate) are defined in library libX, and libY and libZ are both using libX (but not knowing aobut each other), and definig for their own purposes getTypeId using first method in X to represent it (note that this doesn't impose anything on libX developer), then they are in agreement about what type X is. If application developer uses libY to get variant and pass it to libZ, both will recognize mentioned type properly.
I am NOT trying to develop type-casting-variant - variant saved as X can be read only as X, even if actual pointer passed to myVariant was Xchild. I am not interested in getting type of topmost class for given instance - just class that was used to create variant.
The C++ FAQ Lite devotes an entire section to Pointers to Member Functions.
Two answers in particular state why what you are trying to do cannot be done (at least, not in a portable way):
C++ introduces a new type of pointer, called a pointer-to-member, which can be invoked only by providing an object. Do not attempt to "cast" a pointer-to-member-function into a pointer-to-function; the result is undefined and probably disastrous. E.g., a pointer-to-member-function is not required to contain the machine address of the appropriate function.
A pointer to a member function might be a data structure rather than a single pointer. Think about it: if it's pointing at a virtual function, it might not actually be pointing at a statically resolvable pile of code, so it might not even be a normal address.