我想知道为什么以下代码是正确的:
void foo(){}
void foo2(void(*)()){};
void foo3(void(*)()&){};
int main(){
foo; // type void(&)() lvalue
foo2(foo); // void(&)() -> void(*)() function to pointer conversion
foo3(foo); // ?? conversion
}
根据function to pointer
转换here
函数类型T的左值可以转换为“指向T的指针”的prvalue。结果是指向函数的指针。
从void(&)()到void(*)()的转换很好,但不是void(*)()&。
这段代码片段(特别是与??一起排列)的正确原因是什么?
foo3
的void(*)()&
参数实际上是一个带有ref-qualifier的函数指针。标准不允许这样做。
C ++ 17标准草案n4659规定:
具有cv-qualifier-seq或ref-qualifier(包括由typedef-name命名的类型)的函数类型应仅显示为:
(6.1) - 非静态成员函数的函数类型, (6.2) - 指向成员的指针引用的函数类型, (6.3) - 函数typedef声明或别名声明的顶级函数类型, (6.4) - type-parameter的默认参数中的type-id,或 (6.5) - 类型参数的template-argument的type-id。
foo3
的参数不符合上述任何标准。最接近你想要做的是(6.2)。
所以你可以这样做:
void foo(){}
class C {
public:
void foo1() & {}
};
void foo2(void(*)()){};
void foo3(void(C::*)()&){};
int main(){
(void) foo;
foo2(foo);
foo3(&C::foo1);
}
这适用于GCC和Clang。 Demo here。