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

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

本文关键字:成员 指针 函数 cast 指向 void reinterpret      更新时间:2023-10-16

成员函数指针不能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(*)()>);
}

戈博尔特在这里

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

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

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

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

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

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


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

这里:

[expr.reinterpret.cast]/11

如果"指向T1的指针"类型的表达式可以使用reinterpret_­cast显式转换为"指向T2的指针"类型,则可以将类型转换为"指向T2的"类型的T1的 glvalue,指定一个对象x。 结果是*reinterpret_­cast<T2 *>(p)的结果,其中p是指向"指向T1的指针"类型的x的指针。...

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