Reputation: 163
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?
Upvotes: 0
Views: 82
Reputation: 22152
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.
Upvotes: 3