【问题标题】:function to pointer reference conversion函数到指针引用的转换
【发布时间】:2019-07-18 02:59:43
【问题描述】:

我想知道为什么下面的代码是正确的:

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 的指针”类型的纯右值。 结果是一个指向函数的指针。

从 void(&)() 到 void(*)() 的转换很好,但不是 void(*)()&。

这段代码sn-p(尤其是??行)正确的原因是什么?

【问题讨论】:

  • 我怀疑它和void(*)()const一样:函数“转换”类型的方法(void(C::*)()& -> void(*)()&)。
  • 当前没有指向foo 的指针可供您参考?
  • clang btw Demo 的错误:“指向函数类型的指针不能有 '&' 限定符”
  • @Jarod42 你是对的,那可能是不允许的。 GCC 不会发出任何类型的警告。
  • 对于一些using,gcc 提供错误Demo,它的行为对我来说似乎是一个错误......

标签: c++ type-conversion implicit-conversion


【解决方案1】:

foo3的参数void(*)()&实际上是一个带有ref-qualifier的函数指针。这是标准不允许的。

C++17 标准草案 n4659 规定:

[dcl.fct]/6

具有 cv-qualifier-seq 或 ref-qualifier 的函数类型(包括由 typedef-name 命名的类型)只能显示为

(6.1) — 非静态成员函数的函数类型,
(6.2) — 指向成员的指针所指的函数类型,
(6.3) — 函数 typedef 声明或别名声明的顶级函数类型,
(6.4) — 类型参数的默认参数中的类型 ID,或
(6.5) — 类型参数的模板参数的类型 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.

【讨论】:

  • 这样的注释通常描述了在其他地方以一种不太容易理解的方式规范地陈述的东西。它声称要形成自己的规则是不寻常的(因为这根本没有法律意义)。因此,我希望我们会发现编译器根本没有回旋余地,但我们需要找到规范原因。
  • 函数类型的引用又在哪里?
猜你喜欢
  • 1970-01-01
  • 2023-03-05
  • 2015-11-03
  • 2012-12-07
  • 2016-06-03
  • 2019-06-18
  • 2012-06-16
  • 1970-01-01
相关资源
最近更新 更多