功能模板推导左值参考和通用参考

时间:2018-11-06 16:19:56

标签: c++ c++11 function-templates forwarding-reference argument-deduction

假设我具有函数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); 好吧。

1 个答案:

答案 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被推导为Tparam的类型为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值,因此Bufint&。 第二次扣减返回Buf==int。这两种推导类型不同,这就是为什么 代码无法编译。