简体   繁体   中英

Cast function to member-function

I want cast function to member-function and then call it, but self has some adjustment to this self_3 = self_1 + self_2

struct Foo {};

namespace FooExt {
    Foo* getSelf(Foo *self) {
        return self;
    }
};

template <typename R, typename T, typename... Args>
auto f2mf(R(func)(T*, Args...)) -> R(T::*)(Args...) {
    return (R(T::*&)(Args...)) func;
}

int main() {
    auto getSelf = f2mf(FooExt::getSelf); // getSelf: (Foo* (Foo::*)(Foo* const)) 0x557f0a9ac210 <FooExt::getSelf(Foo*)>, this adjustment 140735536657056

    Foo f{};

    auto self_1 = &f;
    auto self_2 = (((Foo*) nullptr)->*getSelf)();
    auto self_3 = (f.*getSelf)();

    return 0;
}

What are the reasons? How to do this properly?

The reasoning below was wrong, because 1. member function pointers are not function pointers and 2. you are not actually casting to a member function pointer type, but to a member function pointer reference type.

The undefined behavior here happens already when you initialize the return value of f2mf from the reference obtained by the cast. It accesses the referenced pointer with the wrong type, causing an aliasing violation and undefined behavior.


The result of explicitly converting a function pointer to another function pointer type is unspecified except that converting back to the original type yields the original pointer value.

Calling the function through a pointer to function type not equal to the original function type causes undefined behavior.

Therefore your compiler can do whatever it wants with the pointer values in your code.

Additionally calling a member function on a null pointer value also causes undefined behavior and also allows the compiler to do whatever it wants.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM