0

A pointer to member function isn't a regular pointer. but a pointer to a pointer to member function does.

struct X {
    void func() {}
};

int main() {
    auto p1 = &X::func;
    auto p2 = &p1;

    // reinterpret_cast<int *>(p1); error!
    reinterpret_cast<int *>(p2);
}

In the code above, a pointer to member function can't be used directly with reinterpret_cast but a pointer to a pointer to member function does. would like to know where does cppreference or draft describe this situation?

6
  • I hope this is only for curiosity, as I can see no valid use-case for something like that. If you think you have an actual use-case, that you're trying to solve an actual problem, then please edit your question to ask about that problem directly instead. Commented Nov 17, 2024 at 12:37
  • 2
    Pointers-to-members aren't pointers, despite the name. (E.g. std::is_pointer returns false on them.) Unlike pointers, they don't store just an address (pointers to data members typically store offsets). Commented Nov 17, 2024 at 12:38
  • 1
    "A pointer to member function isn't a regular pointer. but a pointer to a pointer to member function does.": That seems to already answer your question. p2 is a regular pointer and can be cast like one. p1 is not and therefore can't be cast like one (with the actual rule pointed out in the answer that has already been posted). Commented Nov 17, 2024 at 12:41
  • The content of your post could work just the same with a title that asks about the non-error case. I certainly had to re-read it from the title down, after answering, to realize you were actually asking about the error. It'd be good if you could make your focus explicit in the body of the post too. Commented Nov 17, 2024 at 12:47
  • Look at your code and thought process. Neither of them makes much sense. &X::func would be a pointer to a member function, p2 would just point to a member function pointer on the heap. Making an int* 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). Commented Nov 17, 2024 at 13:06

1 Answer 1

3

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.