【问题标题】:Understanding type deduction for universal references理解通用引用的类型推导
【发布时间】:2018-03-15 13:37:15
【问题描述】:

foo为函数:

template< typename T >
void foo( T&& a ){}

下面的foo调用将推导出T的类型:

foo( 0 ); // is T here int or int&& ?

int a = 0;
foo( a ); // is T here int or int& ?

【问题讨论】:

  • 您可以尝试使用不同的类型特征,如 en.cppreference.com/w/cpp/types/is_reference 或 std::is_same.. 并使用 std::add_lvalue_reference 等构建类型,然后查看特征的值是什么
  • 这是一个示例,您可以看到自己测试的方法:wandbox.org/permlink/51APJ9Pr4fsweWrF
  • 这是调试类型的技巧:template &lt;typename T&gt; class TD;,然后在 foo 中使用:TD&lt;T&gt;();。由于没有定义TD,编译器会报错,并且在错误信息中,好的编译器会显示T的类型。

标签: c++ function templates type-deduction forwarding-reference


【解决方案1】:

类型推导的默认规则是引用类型永远不能是推导的结果。鉴于此代码,

template <class T>
void bar(T par);

bar(0);
int a;
bar(a);
int &b;
bar(b);

所有 3 个呼叫都将呼叫 foo&lt;int&gt;。也就是说,T 被推导出为int 并且parint 类型。

转发引用通过简单添加一条规则来工作:当用于转发引用的类型推导的参数(即,推导T的参数T&amp;&amp;)的左值是类型X,使用X &amp;类型代替X进行推导。

注意,这意味着给定类型X,只有XX &amp; 可以是类型推导的结果; X &amp;&amp; 永远不可能。

让我们分析您的代码(我将重命名他的函数参数,以明确我所指的内容):

template <class T>
void foo(T &&par);

foo(0);

int a;
foo(a);

在第一种情况foo(0),参数是int类型的右值,因此int类型用于类型推导,这意味着T被推导为int(调用的函数是@ 987654342@),par 的类型是int &amp;&amp;

在第二种情况foo(a) 中,参数是int 类型的左值。转发参考规则启动,int &amp; 类型用于扣除。因此T推导为int &amp;(调用的函数为foo&lt;int&amp;&gt;),par的类型为“int &amp; &amp;&amp;”,折叠为int &amp;

【讨论】:

    【解决方案2】:

    表达式T&amp;&amp;推断的上下文就像你提供的那样

    template< typename T >
    void foo( T&& a ){}
    

    即 T 是根据提供的参数推导出来的,受制于 reference collapsing rules.

    总之;

    • 如果提供的参数是typeT&amp;&amp; 类型的左值 将展开为type&amp; &amp;&amp;,然后折叠为type&amp;

    • 如果提供的参数是typeT&amp;&amp; 类型的右值 将展开为type &amp;&amp;,然后折叠为type&amp;&amp;

    注意两者都是引用,如果需要触发右值 另一个函数的重载,你需要做std::forward&lt;T&gt;(a)

    【讨论】:

      【解决方案3】:

      foo(0); // 这里的 T 是 int 还是 int&& ?

      一个int

      int a = 0; 富(一); // 这里的 T 是 int 还是 int& ?

      一个int&amp;

      【讨论】:

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