2012-05-03 56 views
11

我最近開始使用C++ 11,並且已經閱讀了有關可變參數模板的教程。我明白,我們可以這樣定義在C++中處理可變參數模板11

// example class that uses variadic template 
template<typename ...Args> struct mtuple; 

一個可變參數模板,但我怎麼能處理mtuple類的模板參數(即會怎麼get<int>(mtuple_obj)樣子?)?

+4

變量模板魔法真的很神奇,你必須試驗它,以及看看許多不同的代碼示例,看看有什麼和爲什麼在那裏。 [這是我編寫自己的Tuple類的嘗試(儘管不要看'Tie()'; D)](https://github.com/griwes/LibRose/blob/master/librosec%2B%2B/tuple .hxx),作爲這樣的代碼示例之一,在這裏也有很多,在SO上瀏覽[tag:variadic-templates]並嘗試理解它們。 – Griwes

+1

幾個有趣的相關問題:http://stackoverflow.com/a/7868427/170521和http://stackoverflow.com/q/7870498/170521 – lurscher

回答

4

什麼get<1>(t)看起來像取決於mtuple的實施。一個典型的實現可以從一個持有每個參數的類型繼承,因此mtuple<A,B,C>繼承自TupleHead<A>(它有一個A類型的成員)並且也從TupleTail<B,C>繼承。 TupleTail<B,C>繼承自TupleHead<B>(其具有類型B的成員)和TupleTail<C>TupleTail<C>繼承TupleHead<C>

現在,如果給每個基類的整數參數太(其具有C類型的成員。):從TupleHead<0,A>

mtuple<A,B,C>繼承和從TupleHead<1,B>TupleTail<1,B,C>

TupleTail<1,B,C>繼承和TupleTail<2,C>

TupleTail<2,C>繼承自TupleHead<2,C>

現在寫get<1>比較簡單,因爲mtuple有一個類型爲TupleHead<1,B>的單個唯一基類,它可以通過upcast獲得,然後返回該基類的B成員。

[編輯:get<1>(m)需要知道對應於元組元素與索引1類型B,爲你使用類似std::tuple_element這也依賴於上述的遞歸繼承層次結構,並使用偏特拿到TupleHead<1,T>基地具有索引1類,然後確定在該部分特,其給出B在我的例子的參數T。]

許多與可變參數模板中使用的技術是有功能的編程技術,諸如模板的第一元件上操作的參數包,然後遞歸地在包的其餘部分做同樣的事情,直到你已經公關覆蓋了所有元素。除了計算其大小(使用sizeof...)或通過實例化另一個模板外,可以直接使用模板參數包做的事情不多,因此通常的方法是實例化另一個模板,將包Args分爲ArgHead, ArgsTail...,並處理頭部,然後遞歸地去做ArgsTail

4

沒有簡單的機制來迭代可變參數模板的值。但是這可以遞歸地完成。這裏有一個例子:

template<typename T, typename... Args> 
void print_values(const char *s, T value, Args... args) 
{ 
    while (*s) { 
     if (*s == '%' && *(++s) != '%') { 
      std::cout << value; 
      ++s; 
      print_values(s, args...); 
      return; 
     } 
     cout << *(s++); 
    } 
} 

所以,如果我叫print_values("%d %d %d", 1, 2, 3)我得到這個遞歸樹:

print_values("%d %d %d", 1, 2, 3) // value -> 1, args... -> 2,3 
print_values("%d %d", 2, 3) // value -> 2, args... -> 3 
print_values("%d", 3) // value -> 3, args... -> NULL 
print_values("") // value -> NULL, args... -> NULL 

我遞歸調用print_values()即使* S == 0檢測到額外的參數

來源:http://en.wikipedia.org/wiki/Variadic_templates