问题描述
假设我具有函数copy
:
template <typename Buf>
void copy(
Buf&& input_buffer,
Buf& output_buffer)
{}
其中input_buffer
是通用引用,而output_buffer
是l值引用.
In which input_buffer
is a universal reference and output_buffer
is an l-value reference.
Reference collapsing rules
确保input_buffer
确实是真的,而不考虑Buf
的推导类型是什么,并且output_buffer
确实是l值参考.
Reference collapsing rules
make sure input_buffer
is indeed, regardless of the deduced type of Buf
, an universal reference and output_buffer
is indeed an l-value reference.
但是,我想知道如何在这里推导Buf
类型.
However, I wonder how type Buf
is deduced here.
我发现copy
传递了一个r值作为input_buffer
,(显然是一个l值传递了output_buffer
),Buf
是一个非引用类型.
I found out that copy
is passed an r-value as input_buffer
, (and an l-value as output_buffer
, obviously) Buf
is a non-reference type.
但是,如果我要传递两个l值,则程序不会编译:
If I were to pass two l-values however, the program does not compile:
int i = 4;
int j = 6;
_copy(i, j);
我希望编译器将Buf
推导出为int&
.遵循引用折叠规则,我希望input_buffer
成为l值引用,即& + && -> &
和output_buffer
也成为l值引用; & + & -> &
.
I would expect the compiler to deduce Buf
to int&
. Following the reference collapsing rules, I would expect input_buffer
to become an l-value reference, that is, & + && -> &
, and output_buffer
to become an l-value reference too; & + & -> &
.
所以问题是:为什么此代码无法编译?
So the question is: Why doesn't this code compile?
(注意:我不一定要寻求解决问题的方法,而只是寻求解释.)
(Note: I am not necessarily asking for a solution to the problem, but for an explanation.)
如果需要详细说明,请随时提问.
If I need to elaborate, feel free to ask.
如果致电:copy(i, j);
GNU GCC编译器提供:错误:没有匹配的函数可以调用'copy(int& ;, int&)'注意:候选:模板无效副本(Buf&&,buf&)注意:模板参数推导/替换失败:注意:推导了参数'Buf'('int&'和'int')的冲突类型
if call: copy(i, j);
GNU GCC Compiler gives:error: no matching function for call to 'copy(int&, int&)'note: candidate: template void copy(Buf&&, buf&)note: template argument deduction/substitution failed:note: deduced conflicting types for parameter 'Buf' ('int&' and 'int')
如果致电:copy<int&>(i, j);
好吧.
推荐答案
a)转发参考的类型推导:
template<class T>
void f(T&& val) {}
当您传递左值T
时,
[a.1]被推导为T&
.所以你有
[a.1] when you pass Lvalue T
is deduced to be T&
. So you have
void f(T& && ){} -after reference collapsing-> void f(T&){}
传递Rvalue T
时,
[a.2]被推导为T
.所以你有
[a.2] when you pass Rvalue T
is deduced to be T
. So you have
void f(T&& ) {}
b)除转发参考之外的参考类型推导:
b) Type deduction for reference except forwarding reference:
template<class T>
void f(T& param){}
当您传递Lvalue时,T
被推导为T
. param
的类型为T&
,但是模板参数为T
,而不是T&
.
when you pass Lvalue, T
is deduced to be T
. param
has type T&
but template argument is T
, not T&
.
所以下面的代码可以编译
So below code compiles
int i = 10;
copy(20,i);
因为第一个参数的类型推导会返回Buf==int
,因为您传递了20个Rvalue.第二个参数的推论结果也返回Buf==int
.所以两者Buf
相同的情况下,代码会编译.
because type deduction for first argument returns Buf==int
since you passed 20 Rvalue.And result of deduction for second argument also returns Buf==int
. So in bothcases Buf
is the same, code compiles.
无法编译的代码:
int i=1;
int j=2;
copy(i,j);
第一个参数的推导类型是什么?您正在传递L值,所以Buf
是int&
.第二次扣减返回Buf==int
.这两种推导类型不同,这就是为什么代码无法编译.
What is deduced type for first argument? You are passing L-value, so Buf
is int&
.Second deduction returns Buf==int
. These two deduced types are not the same, that is whycode doesn't compile.
这篇关于功能模板推导左值参考和通用参考的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!