【问题标题】:Forwarding of parameters from templates to functions of different types将参数从模板转发到不同类型的函数
【发布时间】:2017-09-06 21:02:57
【问题描述】:

我正在试验模板和转发。写了一些让我吃惊的简单实验代码。我想更好地理解这个机制,可能我在这里缺乏一些知识,因此我请求帮助。您能否解释一下为什么我在下面的代码中的两个调用无法编译(PLACE 2 和 3)?

#include <iostream>
#include <memory>
#include <utility>
using namespace std;

void h2rvalref(int&& i) { cout << "h2rvalref" << endl; }
void h2ref(int& i) { cout << "h2ref" << endl; }
void h2val(int i) { cout << "h2val" << endl; }

template <class T, class X>
void h1(T&& t, X x) { x(forward<T>(t)); }

int main()
{    
    // PLACE (1)
    h1<int, decltype(h2rvalref)>(1, h2rvalref);

    auto b = 1;
    // PLACE (2)
    // h1<int, decltype(h2ref)>(b, h2ref); // --> ERROR - no matching function..., cannot convert 'b' (type 'int') to type 'int&&'

    // PLACE (3)
    // h1<int, decltype(h2val)>(b, h2val); // --> ERROR - no matching function..., cannot convert 'b' (type 'int') to type 'int&&'
}

我不明白为什么当我有 int 类型的值 b 时,错误说明了将 int 转换为 int&& 的内容。

【问题讨论】:

  • 不要注释掉您询问的代码。语法突出显示使其难以阅读。
  • 好的,我会记住的。

标签: c++


【解决方案1】:

问题在于您正在为函数提供显式模板参数。当您为要转发的类型显式提供模板参数时,转发参数不起作用(除非您真的知道自己在做什么)。

template <class T, class X>
void h1(T&& t, X x) { x(forward<T>(t)); }

当你写h1&lt;int, decltype(h2ref)&gt;时,你会得到这样一个函数:

void h1(int&& t, decltype(h2ref) x) { x(forward<int>(t)); }

int&amp;&amp; 是与int 不同的类型,不能绑定到int 类型的左值,例如您传入的b;它只能绑定到int类型的右值


如果你不使用模板参数,它就可以工作:

h1(b, h2ref);

这将实例化一个如下所示的函数:

void h1(int& t, // int& && collapses to just int&
        decltype(h2ref) x) {
    x(forward<int&>(t));
}

【讨论】:

  • "int&& 是与 int 不同的类型,不能从 int 隐式创建"恕我直言,这是一个非常阴暗的解释。 int 是一种类型,int&amp;&amp; 可以绑定到该类型的表达式,但前提是该表达式的值类别(不同于类型)是右值。出现此问题的原因是 int&amp;&amp; 无法绑定到 int 类型的左值。
  • @NirFriedman 为什么将intint&amp;int&amp;&amp; 视为完全不同的类型,其转换规则与C++ 的左值/右值规则相匹配?
  • 它们不同的类型,但是“不能从 int 隐式创建”有多个问题。首先,引用不像普通的 C++ 类型,它隐式/显式地从另一种类型创建,而是引用具有绑定规则,它们是绑定的。其次是你原来陈述的要点甚至不是真的; int&amp;&amp; 在某些情况下可以绑定到int,但在其他情况下则不行。三是你看待事物的方式,除了把类型构造和绑定混在一起,还把类型和值范畴混在一起,需要分别理解。
猜你喜欢
  • 2017-05-10
  • 2017-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-12
  • 2018-03-31
相关资源
最近更新 更多