reinterpret_cast 指向 void(*&)() 的成员函数指针

reinterpret_cast member function pointer to void(*&)()

成员函数指针不能reinterpret_cast到函数指针。 (不过,GCC 需要 -pedantic-errors 标志来强制执行。)

但是 GCC、Clang 和 MSVC 似乎同意将 成员函数指针 转换为 对函数指针 的引用是可以的。请参阅以下示例:

#include<type_traits>

struct A {
    void f() {}
};

int main() {
    auto x = &A::f;
    auto y = reinterpret_cast<void(*&)()>(x);
    // auto y = reinterpret_cast<void(*)()>(x);
    static_assert(std::is_same_v<decltype(y), void(*)()>);
}

Godbolt here

此程序可在所有三个编译器上编译,但在使用注释掉的行而不是前一个时无法在所有编译器上编译(带有迂腐的标志)。

我在标准中没有看到任何允许这种转换的规则。程序格式错误并且编译器无法诊断它还是程序格式正确?

如果是后者,确切的转换顺序是什么,标准在哪里允许它,函数指针可以转换回原始类型以便调用它还是使用引用来初始化y 已经是未定义的行为?

reinterpret_cast<T&>(x) 等同于 *reinterpret_cast<T*>(&x).

换句话说,reinterpret_cast<void(*&)()>(x) 对指针本身执行类型双关。

像往常一样访问此转换的结果违反了严格的别名并导致未定义的行为。


I don't see any rule in the standard allowing this conversion.

这里:

[expr.reinterpret.cast]/11:

A glvalue of type T1, designating an object x, can be cast to the type “reference to T2” if an expression of type “pointer to T1” can be explicitly converted to the type “pointer to T2” using a reinterpret_­cast. The result is that of *reinterpret_­cast<T2 *>(p) where p is a pointer to x of type “pointer to T1”. ...

由于 reinterpret_cast 指向对象类型的指针之间(在您的情况下,指向指向指针(指向 [成员] 函数)的指针之间)始终是允许的,因此在您的情况下也是允许的。