1. Variadic Template 模板參數可變

介紹

模板的參數在照往常來說是固定的大小之後讓編譯器進行推導,但是現在c++11出現了新的東西就是模板函數的參數可以使不確定的。下面來看一個實例

template <typename T , typename... Types>
void Print(const T & FirstArg,const Types &... arg)
{
    cout << firstAge <<endl;
    Print(args...);
}

上面所有加上...的部分不是省略,而是語法的要求,所以這個位置都是語法的規定。我們輸入的參數可以是任意的。將變量前後分開,分爲第一個模板參數,和後面的一堆參數。然後會循環調用自己,將後面的包的內容傳進Print函數裏面。

需要注意的點

其實後面的這些變臉就是一個所謂的pack,用於模板參數就是模板參數包,用在函數類型裏面就是函數類型包。

當最後一個元素沒有的時候,還需要設計一個函數,最後一次調用這個函數結束遞歸調用。如果沒有處理最後一種沒有參數的情況的函數的話,編譯器就會報錯。

如果我們想知道傳進來的參數個數

調用sizeof...(args),這個...在sizeof的後面

一個令人震驚的點

看下面的這個函數

template<typename... Types>
void print(const Types&... args)
{ /*...*/}

這個函數我們會認爲它和上面的那個函數是有重複的,編譯應該是不過的,但是並沒有其實是可以並存的。至於說每次傳進來的數據怎麼去使用,這個的話還需要實驗去確定,但是我個人估計,編譯器在編譯的時候會查看每個模板的一個特化的情況,有的時候模板都是打包的,但是有一些變量是特化出來的,所以更加符合要求,編譯器就會優先使用這些函數。

Tuple的例子

首先看一下Tuple的代碼裏面應用到這個可變模板參數的地方

template <typename... Values> class tuple;
template<> class tuple<>{};
//這裏面可以看到的是tuple是繼承於後面的包的類型的
//這一點應用起來就很牛逼
template<typename Head,tyepname... tail>
class tuple<Head,Tail...>:private tuple<Tail...>
{
   //我都不知道這都能進行typedef
   typedef tuple<Tail...> inherited;
   public:
    tuple(){}
    typle(Head v,Tail... tail)
    :m_head(v),inherited(tail...){}
    //head賦給了我們的成員變量 m_head,然後這個繼承關係就是遞歸的繼承
    //最後我們需要寫出一個沒有元素初始化的tuple在最上面,來退出遞歸。
    
    typename Head::type head() {return m_head;}
    inherited & tail() {return *this}
   private:
    Head m_head;

簡單解釋一下上面的例子

也就是說你個一個tuple變量幾個參數傳進去之後,假如我們使用的下面這個例子的變量

tuple<int,string,float> eg(1,"hello world",1.02);

這個例子裏面,首先就是類型的一個繼承關係 int (m_head(1)) ->string(m_head("hello world"))->float(m_head(1.02)),也就是說tuple<float>類型是所有的其他類型的父類,然後float再去繼承那個空的tuple。

這個例子就已經很方便的解釋了可變模板參數的作用,但是有幾個注意點

1.需要添加遞歸的結束條件(變量,函數等等),不然編譯會報錯

2.需要注意函數的特化和泛化程度,這樣才能正確調用到合適的參數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章