【问题标题】:Function template deduction l-value reference and universal reference函数模板推导左值引用和通用引用
【发布时间】:2018-11-06 16:19:55
【问题描述】:

假设我有函数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&amp;。按照引用折叠规则,我希望input_buffer 成为左值引用,即&amp; + &amp;&amp; -&gt; &amp;,并且output_buffer 也成为左值引用; &amp; + &amp; -&gt; &amp;.

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

(注意:我不一定要求解决问题,而是要求解释。)

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

编辑: 如果来电:copy(i, j); GNU GCC 编译器提供: 错误:没有匹配函数调用'copy(int&, int&)' 注意:候选:模板无效副本(Buf&&,buf&) 注意:模板参数扣除/替换失败: 注意:推断参数'Buf'('int&'和'int')的冲突类型

如果调用: copy&lt;int&amp;&gt;(i, j); 好的。

【问题讨论】:

  • 我不知道Buf是否可以同时推断为通用参考和普通参考。将函数模板化为两种类型确实可以解决问题,但比您可能想要的更受限制。顺便说一句,最好包含MCVE,包括您收到的编译器错误。

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


【解决方案1】:

a) 转发参考的类型扣除:

template<class T>
void f(T&& val) {}

[a.1] 当你传递左值时,T 被推导出为T&amp;。所以你有

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&amp;,但模板参数是 T,而不是 T&amp;

所以下面的代码编译

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

因为第一个参数的类型推导返回 Buf==int,因为您传递了 20 个右值。 第二个参数的推导结果也返回Buf==int。所以在这两个 case Buf 相同,代码编译。

无法编译的代码:

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

第一个参数的推导类型是什么?您正在传递 L 值,因此 Bufint&amp;。 第二次扣除返回Buf==int。这两种推导的类型不一样,这就是为什么 代码无法编译。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多