使用带有和没有&符号的函数名称之间的区别是什么?我注意到,当绑定到模板参数时,它们的行为方式不同:
void foo();
template <typename F> void bind(F&);
bind(foo); // OK
bind(&foo); // Error
为什么会这样?在这些情况下推导出的类型是什么?
答案 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
不是匿名临时的,因此允许绑定到引用。