为什么指向函数的指针不能绑定到左值引用,而函数可以?

时间:2017-01-25 13:52:34

标签: c++ templates reference function-pointers

使用带有和没有&符号的函数名称之间的区别是什么?我注意到,当绑定到模板参数时,它们的行为方式不同:

void foo();
template <typename F> void bind(F&);
bind(foo);  // OK
bind(&foo); // Error

为什么会这样?在这些情况下推导出的类型是什么?

2 个答案:

答案 0 :(得分:4)

请注意,内置operator&将返回T*类型的 prvalue 。所以&foo将返回一个类型为void (*)()的函数指针,它是一个prvalue,不能绑定到非const的左值引用;这正是bind()期望的参数,然后就失败了。

对于bind(foo),模板pamareter F将被精确推导为函数类型(即void()),然后bind的参数类型将为void(&)() },所以它有效。

您可能认为foo&foo应该具有相同的效果,因为函数到指针衰减。但请注意,bind()的参数被声明为传递引用。然后对于bind(foo),函数到指针的衰减不会发生,这就是为什么参数类型被推断为函数的引用。另一方面,对于bind(&foo),显式调用operator&以返回函数指针prvalue,该函数指针prvalue不能传递给bind()

如果参数被声明为按值传递,则会发生函数到指针的衰减,然后bind(foo)bind(&foo)将产生相同的效果,并且两者都可以正常工作。

void foo();
template <typename F> void bind(F);
bind(foo);  // OK, F=void(*)()
bind(&foo); // same as above

答案 1 :(得分:2)

&foo匿名临时,因此无法绑定到非const引用。

如果你写过

template <typename F> void bind(const F&);

然后编译就会成功。

foo不是匿名临时的,因此允许绑定到引用。