Search code examples
c++pointer-to-memberreinterpret-cast

Cast one pointer-to-member-function to another of same class


Is it legal to cast a pointer-to-member-function to another pointer-to-member-function of the same class using reinterpret_cast? The following example works. But is it legal?

#include<iostream>
#include<vector>
#include<string>

class A
{
    public:
    void func_int(int x) { std::cout << x << std::endl; }
    void func_string(std::string const& x) { std::cout << x << std::endl; }
};

int main()
{
    std::vector<void(A::*)()> v;
    v.push_back(reinterpret_cast<void(A::*)()>(&A::func_int));
    v.push_back(reinterpret_cast<void(A::*)()>(&A::func_string));
    A a;
    (a.*reinterpret_cast<void(A::*)(int)>(v[0]))(5);
    (a.*reinterpret_cast<void(A::*)(std::string const&)>(v[1]))(std::string{"Test"});

    return 0;
}

Solution

  • At [expr.reinterpret.cast] the C++ draft states:

    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.72 The null member pointer value ([conv.mem]) 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.

    72) T1 and T2 may have different cv-qualifiers, subject to the overall restriction that a reinterpret_cast cannot cast away constness.

    Since you are converting your "pointer to member function" to a different "pointer to member function" type and back, it yields the original value. This is both legal and well-defined behaviour. So your code should work properly.