函数模板推导左值引用和通用引用

Function template deduction l-value reference and universal reference

假设我有函数 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_bufferBuf 是非-引用类型。

但是,如果我要传递两个左值,程序将无法编译:

int i = 4;
int j = 6;

_copy(i, j);

我希望编译器将 Buf 推断为 int&。遵循引用折叠规则,我希望 input_buffer 成为左值引用,即 & + && -> &,并且 output_buffer 也成为左值引用; & + & -> &.

所以问题是:为什么这段代码不能编译?

(注:我不是求问题的解决方法,而是求解释。)

如果我需要详细说明,请随时询问。

编辑: 如果打电话:copy(i, j); GNU GCC 编译器给出: 错误:没有匹配函数来调用 'copy(int&, int&)' 注意:候选:template void copy(Buf&&, buf&) 注意:模板参数 deduction/substitution 失败: 注意:推断出参数 '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] 当你传递右值时 T 被推断为 T。所以你有

void f(T&& ) {}

b) 除转发引用:

外引用的类型推导
template<class T>
void f(T& param){}

当你传递左值时,T被推导为Tparam 具有类型 T& 但模板参数是 T,而不是 T&

所以下面的代码可以编译

int i = 10;
copy(20,i);

因为第一个参数的类型推导 returns Buf==int 因为你传递了 20 个右值。 第二个参数的推导结果也是 returns Buf==int。所以在两者 cases Buf 相同,代码编译。

无法编译的代码:

int i=1;
int j=2;
copy(i,j);

第一个参数的推导类型是什么?您传递的是 L 值,因此 Bufint&。 二扣returnsBuf==int。这两个推导的类型不一样,这就是为什么 代码无法编译。