1

Reading the answer to this question (Casting a function pointer to another type), I understand that it is safe to cast pointers like void(*)(A*) to pointers like void(*)(B*), you just need to cast them back before calling them.

Does this also work for member function pointers? Can I safely cast void(A::*)() to void(B::*)() and cast it back before calling it?

Example code that seems to work at least on my system:

#include <iostream>

struct A {
  void f() { std::cout << "called" << std::endl; }
};

struct B {};

int main() {
  A instance;
  auto ptr = reinterpret_cast<void (B::*)()>(&A::f);
  (instance.*(reinterpret_cast<void (A::*)()>(ptr)))();
}
user3684240
  • 1,420
  • 2
  • 12
  • 18

3 Answers3

3

I believe, yes. Here is what I find in standard (5.2.10):

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. The null member pointer value (4.11) is converted to the null member pointer value of the destination type. The result of this conversion is unspecified, except in the following cases:

— converting a prvalue of type “pointer to member function” to a different pointer to member function type and back to its original type yields the original pointer to member value.

— converting a prvalue of type “pointer to data member of X of type T1” to the type “pointer to data member of Y of type T2” (where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer to member value.

Community
  • 1
  • 1
SergeyA
  • 61,605
  • 5
  • 78
  • 137
3

From 5.2.10/10 (reinterpret_cast) we learn:

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.71 The null member pointer value (4.11) is converted to the null member pointer value of the destination type. The result of this conversion is unspecified, except in the following cases:

  • converting a prvalue of type “pointer to member function” to a different pointer to member function type and back to its original type yields the original pointer to member value.

In this case you're casting to and from pointer-to-member-function (both point to functions), so it looks like it's totally legal.

Mark B
  • 95,107
  • 10
  • 109
  • 188
-1

5.4 [expr.cast] says that you can use reinterpret_cast to convert a pointer-to-member-of-derived to a pointer-to-member-of-base and back. Of course, you have to convert back to the derived type in order to use the pointer, since there is no guarantee that the function it points to is actually a member of the base.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • Irrelevant, question is not about derived classess. – SergeyA Mar 22 '16 at 15:37
  • @SergeyA - sigh. It's about **casts**, and that's one of the legal casts. – Pete Becker Mar 22 '16 at 15:37
  • It is, but it doesn't answer the question in any way. Mine and Mark's answers do. – SergeyA Mar 22 '16 at 15:39
  • 1
    @SergeyA - thank you for your input. Your comments are always so constructive. – Pete Becker Mar 22 '16 at 15:42
  • Ok, I can explain my point. Your answer might have been useful under different circumstances. If the only allowed conversion was between pointers to members of two classess in inheritance relationship (which is not the case), your answer could be like following: 'According to Standard, the only allowed conversion is between derived and parent class, and since classes in your example are unrelated, the conversion is not safe'. This would be a helpful and meaningful answer. – SergeyA Mar 22 '16 at 15:49
  • But it is not the case, so this answer does not help. It is the same if someone was asking 'can I override an `operator+`', and you would be replying that you can override `operator-`. Yes you can, but it is not helpful to OP. – SergeyA Mar 22 '16 at 15:50
  • @SergeyA - I see where your confusion comes from; you're overlooking the fact that converting a pointer-to-member-of-derived to a pointer-to-member-of-base **is** converting a pointer to member of one class into a pointer to member of another class. The fact that there can be **other** conversions does not make this one not a conversion. – Pete Becker Mar 22 '16 at 16:00
  • There is no confusion on my side. I am perfectly aware that it is a conversion. It is just not the conversion OP is asking about. Look at OPs example - there are no inheritence there. You are narrowing the question undully. If you do not like my former analogy, here is possibly a better one: Someone is asking *Is it possible to overload operators in C++*, provides an example where overload of `operator+` is approriate and you reply 'You can overload `operator-`'. Yes, it is true, but it is undully narrowing, and more importantly, might be read as if it's the only overload available. – SergeyA Mar 22 '16 at 16:04
  • And your answer actually borders with now deleted answer from @JonathanWakely, only that he said that this is the only allowed conversion, and you are not saying that (but your answer could be read in this way), which makes your answer formally correct. – SergeyA Mar 22 '16 at 16:17
  • @SergeyA - again, thank you for your input. Enlightening, as always. – Pete Becker Mar 22 '16 at 16:36
  • My pleasure, Pete. Feel free to ask anytime, this is what SO is for - to enlighten, to educate, to open new horizons. – SergeyA Mar 22 '16 at 16:43