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

wal*_*nut 6 c++ member-function-pointers function-pointers language-lawyer reinterpret-cast

成员函数指针不能是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(*)()>);
}
Run Code Online (Sandbox Code Playgroud)

上帝在这里

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

我在标准中看不到任何允许这种转换的规则。程序格式错误,编译器无法对其进行诊断还是程序格式正确?

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

Hol*_*Cat 6

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

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

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


我在标准中看不到任何允许这种转换的规则。

这里:

[expr.reinterpret.cast] / 11

如果可以使用a 将类型为“ pointer to ” 的表达式显式转换为类型“ pointer to ” ,则可以将T1指定对象的类型的glvalue强制转换为x“ reference to T2”类型。结果是where 是指向“ pointer to ” 类型的指针。...T1T2reinterpret_­cast*reinterpret_­cast<T2 *>(p)pxT1

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