假设我具有函数copy
:
template <typename Buf>
void copy(
Buf&& input_buffer,
Buf& output_buffer)
{}
其中input_buffer
是通用引用,而output_buffer
是l值引用。
Reference collapsing rules
确保input_buffer
确实是真实的,而不考虑Buf
的推导类型,并且是通用引用,而output_buffer
确实是l值引用。
但是,我不知道如何在这里推导类型Buf
。
我发现copy
传递了一个input_buffer
的r值(显然还有一个output_buffer
的l值)Buf
是一个非引用类型。
但是,如果我要传递两个l值,则程序不会编译:
int i = 4;
int j = 6;
_copy(i, j);
我希望编译器将Buf
推导为int&
。遵循引用折叠规则,我希望input_buffer
成为l值引用,即& + && -> &
和output_buffer
也成为l值引用; & + & -> &
。
所以问题是:为什么这段代码不能编译?
(注意:我不一定要寻求解决问题的方法,而只是寻求解释。)
如果需要详细说明,请随时提问。
编辑:
如果致电:copy(i, j);
GNU GCC编译器提供:
错误:没有匹配的函数可以调用'copy(int&,int&)'
注意:候选:模板无效副本(Buf &&,buf&)
注意:模板参数推导/替换失败:
注意:推导了参数'Buf'的冲突类型('int&'和'int')
如果致电:
copy<int&>(i, j);
好吧。
答案 0 :(得分:1)
a)转发参考的类型推导:
template<class T>
void f(T&& val) {}
[a.1]当您传递左值T
时被推导为T&
。所以你有
void f(T& && ){} -after reference collapsing-> void f(T&){}
[a.2]当您传递右值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);
因为自您传递20 Rvalue后,第一个参数的类型推导返回Buf==int
。
第二个参数的推论结果也返回Buf==int
。所以两者
Buf
相同的情况下,代码会编译。
无法编译的代码:
int i=1;
int j=2;
copy(i,j);
第一个参数的推导类型是什么?您正在传递L值,因此Buf
是int&
。
第二次扣减返回Buf==int
。这两种推导类型不同,这就是为什么
代码无法编译。