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

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

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

我希望编译器能够推断出 Bufint& 。遵循引用折叠规则,我期望 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 被推导为 Tparam 的类型为 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 值,因此 Bufint&。 第二次推导返回 Buf==int。这两个推导的类型并不相同,这就是为什么 代码无法编译。

关于c++ - 函数模板推导左值引用和通用引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53175851/

相关文章:

c++ - 输入流上的基于范围的循环

c++ - C++ 自由函数可以别名吗?

c++ - 在没有包含的情况下找不到其他命名空间中的对象,否则文件相同

c++ - 在 C/C++ 中读取和解析行;将标记放入数组或 vector 或类似结构中

C++ unique_ptr 和映射

c# - 如何为表单控件创建模板函数?

c++ - (SFINAEd) 模板函数的宏

c++ - 是否值得只包含 type_traits 以获得枚举的基础类型?

c++ - 帮助使用 boost.log 和 boost.build (bjam) 别名,构建并包含在目标中

c++ - 在 C++11 中设置 std::thread 优先级的可移植方法