函数类型的值性(右值/左值)重载
Overloading on valueness (rvalue/lvalue) of a function type
是否可以调用一个对函数进行右值引用的函数?例如:
#include <iostream>
void foo(void(&f)(int))
{
std::cout << "A" << std::endl;
}
void foo(void(&&f)(int))
{
std::cout << "B" << std::endl;
}
我可以调用打印"B"的foo
的过载吗?
这是不可能的。
当你有两个这样的候选函数时,对函数类型进行左值引用的重载总是优先于右值引用重载。函数在所有情况下都被认为是左值,因此对左值引用的转换是最强的。以下是一些标准措辞([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错误为:
对类型
void (int)
的非常值引用无法绑定到类型wrap
的临时值
GCC显然是错误的,因为上面的引用,但Clang也是错误的。运算符函数的结果是一个左值,因此它应该绑定到左值重载,但clang似乎没有尝试转换。一个更简单的例子是:
void (&r)(int) = wrap{}; // OK in gcc, error in clang
所以这看起来像是Clang和GCC中的一个bug。
相关文章:
- 传递空初始值设定项列表时使用右值和左值引用候选项的重载解析
- 字符串文本左值和右值引用的函数重载
- 重载运算符返回什么类型的值(对于用户定义的类型):右值还是左值?
- 如何重载下标运算符以返回可以是左值的可选值?
- 重载右值和左值引用的工厂函数 - 高效初始化
- 为什么常量左值引用在重载解析期间优先于常量右值引用
- 手动选择重载函数为右值或左值类型
- 如何区分重载函数的左值和右值成员函数指针
- 为什么运算符 [] 不重载左值和右值?
- 如何避免重载赋值运算符将右值转换为左值
- 运算符重载所需的左值作为赋值的左操作数
- MSVC++为左值而不是右值使用基运算符=重载
- 模板中的右值引用和常量左值引用之间的重载
- 在什么情况下,运算符=应该用左值/右值重载而不是复制和交换来实现
- 重载运算符<<:无法将左值绑定到"std::basic_ostream<char>&&"
- 为什么常量左值与给定 T&& 和常量 T& 重载的常量右值绑定不同?
- 重载istream_iterator ----无法将左值绑定到"std::basic_istream<char>&&"
- 将右值引用作为左操作数重载加法操作符被认为是一种良好的做法
- 是否需要重载接受const左值引用的方法来显式地进行右值引用?
- 重载运算符<<:无法将"std::<char>basic_ostream"左值绑定到"std::basic_ostream<char>&&"