假设我有函数 copy
:
template <typename Buf>
void copy(
Buf&& input_buffer,
Buf& output_buffer)
{}
其中input_buffer
是通用引用和 output_buffer
是左值引用。
Reference collapsing rules
确保input_buffer
确实如此,无论 Buf
的推导类型如何,通用引用和 output_buffer
确实是一个左值引用。
但是,我想知道如何输入 Buf
推导到这里。
我发现copy
传递一个右值 input_buffer
,(显然左值为 output_buffer
) Buf
是非引用类型。
但是,如果我传递两个左值,则程序无法编译:
int i = 4;
int j = 6;
_copy(i, j);
我希望编译器能够推断出 Buf
至int&
。遵循引用折叠规则,我期望 input_buffer
成为左值引用,即& + && -> &
,和output_buffer
也成为左值引用; & + & -> &
.
所以问题是:为什么这段代码不能编译?
(注意:我不一定是要求问题的解决方案,而是要求解释。)
如果我需要详细说明,请随时询问。
编辑:
如果调用:copy(i, j);
GNU GCC 编译器给出:
错误:没有匹配的函数可用于调用“copy(int&, int&)”
注意:候选人:模板无效拷贝(Buf&&,buf&)
注意:模板参数推导/替换失败:
注意:推导出参数“Buf”(“int&”和“int”)的冲突类型
如果调用:
copy<int&>(i, j);
好的。
最佳答案
a) 转发引用的类型推导:
template<class T>
void f(T&& val) {}
[a.1] 当您传递左值时,T
被推导为 T&
。所以你有
void f(T& && ){} -after reference collapsing-> void f(T&){}
[a.2] 当您传递 Rvalue T
时,将被推导为 T
。所以你有
void f(T&& ) {}
b) 类型推导供引用,转发引用除外:
template<class T>
void f(T& param){}
当您传递左值时,T
被推导为 T
。 param
的类型为 T&
,但模板参数是 T
,而不是 T&
。
下面的代码可以编译
int i = 10;
copy(20,i);
因为第一个参数的类型推导返回 Buf==int
,因为您传递了 20 个右值。
第二个参数的推导结果也返回 Buf==int
。所以在两者中
情况 Buf
相同,代码可以编译。
无法编译的代码:
int i=1;
int j=2;
copy(i,j);
第一个参数的推导类型是什么?您正在传递 L 值,因此 Buf
是 int&
。
第二次推导返回 Buf==int
。这两个推导的类型并不相同,这就是为什么
代码无法编译。
关于c++ - 函数模板推导左值引用和通用引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53175851/