是否可以调用一个对函数进行右值引用的函数?例如:
#include <iostream>
void foo(void(&f)(int))
{
std::cout << "A" << std::endl;
}
void foo(void(&&f)(int))
{
std::cout << "B" << std::endl;
}
我可以调用foo
的重载来打印&#34; B&#34;?
答案 0 :(得分:2)
这是不可能的。
当你有两个这样的候选函数时,对函数类型进行左值引用的重载是总是优先于rvalue引用过载。在所有情况下,函数都被认为是左值,因此转换为左值引用是最强的。这是一些标准措辞([over.ics.rank] /p3.2.4):
标准转换序列
S1
是比标准转换序列S2
更好的转换序列,如果
S1和S2是引用绑定(8.5.3),S1将左值引用绑定到函数左值,
S2
将右值引用绑定到函数左值。 [例如:int f(void(&)()); // #1 int f(void(&&)()); // #2 void g(); int i1 = f(g); // calls #1
- 结束示例]
此处提供的评论中的代码调用gcc中的重载#2并被clang拒绝。
void foo(void(&)(int)); // #1
void foo(void(&&)(int)); // #2
void f(int);
struct wrap {
using T = void(&&)(int);
operator T() { return f; }
};
int main() {
foo(wrap{}); // Calls #2 in gcc, error in clang
}
Clang错误是:
由于以上引用,GCC显然是错误的,但Clang也是错误的。运算符函数的结果是左值,因此它应该绑定到左值超载,但似乎clang没有尝试转换。一个更简单的例子是:对类型
void (int)
的非常量左值引用无法绑定到wrap
类型的临时值
void (&r)(int) = wrap{}; // OK in gcc, error in clang
所以这看起来像是Clang和GCC中的一个错误。