Question

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.

Was it helpful?

Solution

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):

  • Pointer-to-member-function is a different animal:

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.

  • Pointer-to-member-functions can point at virtual functions:

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.

OTHER TIPS

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.

RTTI is not limited by translation units. The only limitations of RTTI around libraries is the DLL boundary, where one DLL would expose a function that returns a derived class. And I'm not 100% sure, but so long as the DLL and executable are all built with the same compiler (and share static libraries), I think it will still work.

In any case, what you're asking for cannot be done. A member pointer is not a pointer, and there is no portable way to get an actual function pointer to a member function.

And even if it could, it wouldn't give you a unique identifier for a type. After all, if a class does not override a function, or if the function isn't virtual, then the address of that member function will be the same for each class that uses it. It will only change if the function is virtual and the class overrides it.

There's no way to make a unique type identifier out of that.

It seems to me that what you want is Boost.Any, which uses RTTI internally to prevent you from casting to the wrong type.


The places where your plan breaks down

You are proposing a getTypeId function which would be implemented like this:

template<typename T>
SomeIdentifierTypedef getTypeId(const T &x)
{
  void *ptr = GetMemberFuncPtr<T>(x, &x::foo);
  return FindIdFromPtr(ptr);
}

This requires the existence of GetMemberFuncPtr, which takes an member pointer and an object, and gets the actual function pointer of that member. This function is intended to return a unique value for every type it receives.

OK, now consider what you have said:

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.

If Y::foo and X::foo are the same member function, then naturally they have the same function pointer. Therefore, getTypeId(Y()) == getTypeId(X()). That violates the stated objective of getTypeId. You want it to return a different value if the type is Y than if it is 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.

This cannot work for two reasons. First, notice that my implementation of getTypeId has ::foo in it. That's because there is no way to talk about an arbitrary method of a class. You have to use a name (and likely a full-fledged signature if you want to be sure) in order to talk about a particular function. You can't just say "get me some function from this type." You have to pick one.

Which means you have to pick the same one for all possible template types of getTypeId. Therefore, all classes that you use getTypeId for must implement the same function.

Oh, you could try to specialize it for certain types. But that runs headlong into the second problem.

Shared libraries do not share functions, unless they are explicitly shared. You cannot share X::foo. The only way for libX to pass libY a class that libY does not have a full and separate definition for is if the class is hidden in some way. So either it's an opaque pointer (void*), in which case you can't even get member functions to it. Or it is a derived class from a definition that both libX and libY have.

That is, there is some (possibly abstract) class base, which both libX and libY were compiled against. libX creates X which is derived from base, and there is some function that libX exposes which returns an X as a base *.

In this case, specialization doesn't help, because only libX has access to the specialization getTypeId<X>. The only way for it to work would be if the specialization were for getTypeId<base>. But then we run back into the problem of what if the user doesn't override the virtual function? Then we think it's still a base.

Even if the test function is a pure-virtual function, that won't help. This is because libX could have a Y which is derived from X which is derived from base. X may have implemented the function, but Y didn't override it. Therefore getTypeId(x) == getTypeId(y) again.

Your idea cannot work.

If you only want to deduce types from each other (so basically create custom RTTI) you could just create a method returning some sort of type identifier.

class MyFirst
{
public:
    inline virtual string GetType() { return "Myfirst"; }
};

Then overload GetType() function for every class you create.

This is usually the simplest method (apart, of course, from dynamic_cast). If you REALLY want to get the type of object from virtual call, you could set a static flag denoting last type used, or return it from every function which said object has.

If you could write HOW you really wanted to "get actual address of code that is executing given method", your question would certainly be clearer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top