【问题标题】:T&& in templated function and class模板化函数和类中的 T&&
【发布时间】:2012-09-07 18:12:00
【问题描述】:

我刚刚在课堂上偶然发现了 T&&,而函数意味着不同的东西。
在功能上:

template<class T> void f(T&& t){};   // t is R or L-value
...
int i=0; 
f(i);   // t in f is lvalue
f(42);  // t in f is rvalue  

在课堂上:

template<class T> 
struct S { 
       S(T&& t){}  // t is only R-value? 
};
...
int i;
S<int> ss(i);   // compile error - cannot bind lvalue to ‘int&&’

这是否意味着如果我们在课堂上有T&amp;&amp; t,那么t 将只是右值?
有人可以指出我可以在哪里获得有关此的更多信息吗?
这是否意味着我需要为 L 和 R 值编写两个方法重载?

回答
正如 Alf 的示例所示,函数和类中的t 可以是左值或右值。

【问题讨论】:

  • t 可以是右值引用或左值引用,但在这两种情况下,t 都是左值。每个函数参数都是一个左值,与类型无关。

标签: c++ c++11 rvalue-reference pass-by-rvalue-reference


【解决方案1】:

你在这里处理模板参数推导。

通过使用f显式定义模板参数,C++ 编译器现在必须从您传递的参数中确定模板参数类型T

&amp;&amp; 类型的模板参数推导规则是特殊的,以允许完美转发。当您使用f(i) 时,T 推导出为T&amp;。因此,参数t 的类型为T&amp; &amp;&amp;,它折叠为T&amp;。但是,当你使用f(42) 时,T 的类型被推导出为T&amp;&amp;,因此tT&amp;&amp; &amp;&amp;,它折叠为T&amp;&amp;

一旦您强制 T 成为特定类型,所有这些都会有效地消失。崩溃仍然可能发生,但是因为您使用了S&lt;int&gt;,所以t 的类型将是int&amp;&amp;S&lt;int&gt; ss(i) 实际上等同于f&lt;int&gt;(i),这也是不合法的。而且由于模板参数推导只适用于函数而不是类型,如果你想要完美的转发,你必须为S做这样的事情:

template<class T> 
struct S { 
    template<class U>
    S(U&& t){}
};

当然,你可以使用SFINAE方法和模板元编程来保证构造函数模板只有在TU的基本类型相同的情况下才能被实例化。

【讨论】:

    【解决方案2】:

    在您的函数中,T 是从实际参数推导出来的。该特定组合的主要用途是完美转发。类模板中T没有推导,必须指定。

    例如,这可以很好地与 g++ 和 msvc 一起编译:

    template<class T> 
    struct S { 
           S(T&& t){}
    };
    
    int main()
    {
        int i;
        S< int& > ss(i);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-23
      • 2011-06-27
      • 1970-01-01
      相关资源
      最近更新 更多