The C++ standard in [expr.reinterpret.cast] does not allow any kind of wild reinterpret_cast, but a long but restrictive list of cases. For pointers to members, the rule is:
Conversions that can be performed explicitly using reinterpret_cast are
listed below. No other conversion can be performed explicitly using reinterpret_cast.
(...)
A prvalue of type “pointer to member of X of type T1” can be explicitly converted to a prvalue of a different
type “pointer to member of Y of type T2” if T1 and T2 are both function types or both object types.
So the following code works:
struct X {
void func() {}
};
struct Y {
void other_func() {}
};
int main() {
auto p1 = &X::func;
auto p2 = &p1;
// reinterpret_cast<int *>(p1); error
reinterpret_cast<void (Y::*)()>(p1); // success
reinterpret_cast<int *>(p2);
}
The reason is probably that the pointer to members are a special kind of pointers that only make sense together with the pointer of an object (I imagine it as a relative pointer to the base of an object, but this is my own imagination and not standard terminology).
std::is_pointerreturns false on them.) Unlike pointers, they don't store just an address (pointers to data members typically store offsets).p2is a regular pointer and can be cast like one.p1is not and therefore can't be cast like one (with the actual rule pointed out in the answer that has already been posted).&X::funcwould be a pointer to a member function, p2 would just point to a member function pointer on the heap. Making anint*out of that would never make sense (unless you have some meta-template type-erasure kind of wrapper that can cast it back to a member function pointer).