• C++11 template parameter deduction


    C++11 引入了右值引用的概念,由此在引出 an rvalue reference to a cv-unqualified template parameter. 在template function 推导中,我们需要推导出template parameter. 

    那么template function的参数推导,有几种形式呢?答案是三种(暂时不考虑加const T的情况), 注意这跟class template不一样,function template 没有偏特化的概念(partial specialization)

    template<typename T>               template<typename T>              template<typename T>

    void func(T t)                               void func(T& t)                            void func(T&& t)

    第一种情况最简单,参数推导也容易。形参和template 参数的类型完全一样,这是因为T t拷贝外部形参。理由很简单,既然是拷贝,那么实参的const属性跟就形参无关。引用更加无关

    int x = 27; // as before

    const int cx = x; // as before

    const int& rx = x; // as before f(x);

    func(x)   // T's and param's types are both int

    func(cx)  // T's and param's types are again both int;

    func(rx)  // T's and param's types are still both int

    func(25) // 25 is rvalue

    第二种情况呢,首先我们分析一下第二种情况,T&t,a lvalue reference to a cv-unqualified  template paramter. 这种情况跟我们通常的fun(int &)类似,只是需要模板推导T.所以实参的const属性会传导到T.

    int x = 27; // x is an int

    const int cx = x; // cx is a const int

    const int& rx = x; // rx is a reference to x as a const int

    the deduced types for param and T in various calls are as follows:

    f(x); // T is int, param's type is int&

    f(cx); // T is const int, // param's type is const int&

    f(rx); // T is const int, // param's type is const int&

    注意template <class T> void func<T& t)不能接受右值.

    那么在C++11之前,如果想template function 的parameter 接受rvalue,怎么办呢?跟普通函数一样,使用const T&

    template<class T >

    void func(const T& t)

    左值右值能接收,编译通过。此时如果类型推导T呢?这种情况就退化成第一种情况。

    c++11 中引入了右值引用的概念,那么在template function中是否也有类似的概念呢?答案是肯定的,但是跟普通的右值引用不同,template中引入的是forwarding reference, 其定义是an rvalue reference to a cv-unqualified template parameter. 

    但是根据template parameter T类型的不同, T&&可能是左值,也可能是右值。这就是Scott Meyers的通用引用。标准里叫做forwarding reference.

    你可能会说,为什么要引入这个概念呢?不是有const T&去接收右值吗?答案是为了完美转发,如果用const T&t ,那么t永远都是左值引用。如果实参是什么。 而通用引用可以区分出右值和右值。那么如果推导呢?

    template<class T>

    void func(T&&t)

    int x = 27; // as before

    constint cx = x; // as before

    const int& rx = x; // as before

    f(x); // x is lvalue, so T is int&, // param's type is also int&

    f(cx); // cx is lvalue, so T is const int&, // param's type is also const int&

    f(rx); // rx is lvalue, so T is const int&, // param's type is also const int&

    f(27); // 27 is rvalue, so T is int, // param's type is therefore int&&

    由此可知,const的属性保留, 当实参是右值的时候,T就是int。我们可以这么理解,因为T&&t是模板参数的右值引用,如果实参是左值,那么T必须加&,通过引用折叠T&& &->T&才能不报错.如果是右值,那么就无需这一步转换

    那么什么是引用折叠呢?根本原因就是C++不支持引用的引用这个概念

    T&& &->T&

    T&  &-> T&

    T&& &&-> T&&

    T& &&->T&

  • 相关阅读:
    BZOJ 1823: [JSOI2010]满汉全席 [2-SAT]
    POJ 3683 Priest John's Busiest Day[2-SAT 构造解]
    Centos出现-bash: unzip: command not found的解决办法
    物理cpu与逻辑cpu概述
    如何正确查看Linux机器内存使用情况
    connections java.net.BindException: Address already in use_解决方案
    Linux查看端口、进程情况及kill进程
    linux如何查看端口被哪个进程占用?
    如何正确查看Linux机器内存使用情况
    TPS和事务响应时间的关系
  • 原文地址:https://www.cnblogs.com/kkshaq/p/10443765.html
Copyright © 2020-2023  润新知