模板/auto

概述

  • 函數模板 編譯器推斷類型,聲明和定義都在頭文件中,
    1.類型參數數組

    template <typename T> foo(T* p){
        T tmp=*p;
        return tmp;
    }

    2.非類型模板,常量表達式值
    實例化
    template <> foo(int *p)函數

  • 類模板 需顯示指出類型
  • 實例化:會實例化全部成員,控制在一處實例化,其餘用extern template引入
  • 模板別名:
    不能用typedef blob <string> strBlob; => <T>錯誤。
    template <typename T> using twin=pair<T,T>
  • 模板的默認參數
    template<class T1, class T2=int>
    class A{};

函數模板類型推斷

  • 只有const轉化,數組、函數到指針的轉換,派生類到基類等都不能應用於模板參數
  • 若兩個模板名稱同樣,實例化類型也要一致
  • 判斷不出類型的須要顯示指定指針

    T1 sum(T2,T3) 
    auto val=sum<long>(i,lng)  //long對應T1
  • 返回類型code

    template <typename It>
    auto fun(It beg,It end)->decltype(*beg)
    //返回非指針,元素的值
    auto fun(It beg,It end)->typename remove_reference<decltype(*beg)>::type;
    //typename表示返回類型,非static變量,remove_reference若T爲X&,X&&則爲X,不然T。
    //相似的還有remote_pointer,add_const等
  • 引用ip

    int i=42;
    int &r = i; //左值,左值引用(能取地址的爲左值)
    const int &r3 = i*42 //右值,const&不可改變,可綁定在一個右值上 ,int &r2=i*42則錯誤
    int &&rr2=i*42 //右值,右值引用
    
    template <typename T> void f1(T&),        f1(ci)✅   f1(i)✅   f1(5)❌
    template <typename T> void f2(const T&),  f2(ci)✅   f2(i)✅   f2(5)✅
    template <typename T> void f3(T&&),       f3(ci)✅   f3(i)✅   f3(5)✅
    //f3(i)由於引用摺疊:X& &,X& &&,X&& & => X& ; X&& &&=>X&&

    std::moveci

    int &&rr3=std::move(rr1) //顯示將一個左值轉移爲對應右值引用類型
    typename name_reference<T>::type&& move(T&& t){
        return static_cast<typename name_reference<T>::type&&>(t)
    }

    std::forwardrem

    //從前面看出&&能夠接受任何左值或者右值參數,但當參數轉發時,第一層T用&&解出後不能用於下層,使用std::forward保持類型
    void flip(F f,T1&& t1,T2&& t2){
        f(std::forward<T2>(t2),std::forward<T1>(t1));
    }
  • auto與template匹配
    template <typename T> void f(ParamType param);
    1.paramType既不是指針也不是引用
    template <typename T> void f(T param);
    若是expr是一個引用,那麼先忽略其引用類型;若是有const,volatile修飾符,則一併忽略。編譯器

    int x = 27; 
    const int cx = x;
    auto x1 = x;        // type is int
    auto x2 = x;        // type is int

    2.ParamType是一個指針或者引用,但不是全局引用
    忽略引用
    template <typename T> void f(T& param); //或T*string

    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
    auto& x1 = x;         // int&
    auto& x2 = cx;        // const int&
    auto& x3 = rx;        // const int&

    3.ParamType是一個全局引用
    template <typename T> void f(T&& param);
    若是expr是一個左值,形式爲A或者A&。那麼T和ParamType的類型都會被推導爲A&。
    若是expr是一個右值,形式爲A&&。則T的類型會被推導爲A,而ParamType的類型會被推導爲A&&。
    auto && x1=x; //x爲右值 ,x1爲x&&,不然x& ,這個只在for中用,忽略吧
    4.數組類型參數
    而在形參爲引用(包括左值引用和全局引用)的時候則會推導出數組的類型,不會退化爲指針io

    const char name[] = "J.P.Briggs";
    template <typename T> void f1(T& param); 
     f1(name);  // T's type and param's type are const char(&)[13]
  • decltype
    在C++ 11中,他惟一的做用就是聲明一個返回類型依賴於模板參數的模板函數,這個功能在使用auto時會出錯

    template <typename Container, typename Index>
    auto access(Container& c, Index i) -> decltype(auto)  
    {
      return c[i];
    }

    C++14

    template <typename Container, typename Index>
    decltype(auto) access(Container&& c, Index i)  // final C++14 version
    {
        return std::forward<Container>(c)[i];
    }

    decltype(e)的類型有以下定義:

    若是e是一個沒有給括號包圍的變量名或者一個沒有被括號包圍的類成員訪問,則decltype(e)的類型就是最終訪問的變量的類型。若是訪問的變量並不存在,則視爲錯誤。

    若是; e是一個函數調用或者重載操做符(若是有括號包圍,則去除括號),則decltype(e)是最終所調用函數的返回值類型;

    不然,若是e是一個左值,且e的類型是T,則decltype(e)爲T&;

    不然 ,decltype(e)的類型就是e的類型。

    const int&& foo();
    int i;
    struct A { double x; };
    const A* a = new A();
    decltype(foo()) x1 = std::move(i); // type is const int&&
    decltype(i) x2; // type is int
    decltype(a->x) x3; // type is double
    decltype((a->x)) x4 = x3; // type is const double&

函數重載

參數個數

template <class T>
void printarg(T t)
{
   cout << t << endl;
}

template <class ...Args>
void expand(Args... args)
{
   int arr[] = {(printarg(args), 0)...};
}

expand(1,2,3,4);

特化

  • 函數模板全特化
    template<>
    匹配:非模板>特化>其餘
  • 函數重載

    template<typename T, class N> void compare(T num1, N num2)  //原模板
    template<> void compare(int num1, double num2)   //全特化
    template<int,double> void compare(int num1, double num2);    template<int,class N> void compare(int num1, N num2)  //報錯
    template<class N> void compare(int num1, N num2)  //函數重載
  • 類模板全特化
  • 類模板部分特化
相關文章
相關標籤/搜索