2012-03-10 74 views
11

Andrei Alexandrescu給予了一個優秀的演講,標題爲:Variadic Templates are Funadic可變模板 - 不同類型的擴展

他提出了以下3個擴展它們subltey不同:

template <class... Ts> void fun(Ts... vs) { 
    gun(A<Ts...>::hun(vs)...); 
    gun(A<Ts...>::hun(vs...)); 
    gun(A<Ts>::hun(vs)...); 
} 

他解釋說:

電話1: 展開所有Tsclass A instatiation, 然後調用hun(vs) 然後擴展所有參數再次通過時進入gun

呼叫2: 展開所有Ts和所有vs分別

呼叫3: Expnads在鎖定步驟,​​即: 展開的Ts參數1和vs 參數1展開的Ts參數2和的vs 參數2展開的可變參數TEMPL的Ts參數n和vs

其他討論參數n ates似乎只涵蓋簡單的可變類模板和可變參數函數,例如typeafe printf等。我不確定這些不同類型的擴展如何影響代碼以及每種類型的用處。

有沒有人有一些演示每種擴展類型應用的例子?

+0

[Variadic Templates pack expansions](http://stackoverflow.com/questions/9182251/variadic-templates-pack-expansions) – kennytm 2012-03-10 22:56:44

+0

@KennyTM不是重複的。這個人想要每種擴展類型的例子(不一定只有那三個alexandrescu顯示的,他展示的只是兩種類型的擴展(一個到模板參數列表,一個到函數參數列表))。 – 2012-03-11 13:39:46

+1

...但是,當他接受一個只顯示這兩種擴展類型的答案時,我想這個問題是不準確的,或者我對問題或兩者缺乏理解...... – 2012-03-11 13:41:21

回答

15
#include <iostream> 
#include <memory> 
#include <typeinfo> 
#include <cstdlib> 
#include <cxxabi.h> 

template <typename T> 
std::unique_ptr<char, void(*)(void*)> 
type_name() 
{ 
    return std::unique_ptr<char, void(*)(void*)> 
      (
       __cxxabiv1::__cxa_demangle(typeid(T).name(), nullptr, 
              nullptr, nullptr), 
       std::free 
      ); 
} 

void display() {} 

template <class T> 
void 
display() 
{ 
    std::cout << type_name<T>().get() << ' '; 
} 

template <class T, class T2, class ...Tail> 
void 
display() 
{ 
    std::cout << type_name<T>().get() << ' '; 
    display<T2, Tail...>(); 
} 

template <class... Ts> 
struct A 
{ 
    template <class... Us> 
     static 
     int 
     hun(Us... us) 
     { 
      std::cout << "A<"; 
      display<Ts...>(); 
      std::cout << ">::hun("; 
      display<Us...>(); 
      std::cout << ")\n"; 
      return 0; 
     } 
}; 

template <class ...T> 
void gun(T...) {} 

template <class... Ts> void fun(Ts... vs) 
{ 
    std::cout << "gun(A<Ts...>::hun(vs)...);\n"; 
    gun(A<Ts...>::hun(vs)...); 
    std::cout << "\ngun(A<Ts...>::hun(vs...));\n"; 
    gun(A<Ts...>::hun(vs...)); 
    std::cout << "\ngun(A<Ts>::hun(vs)...);\n"; 
    gun(A<Ts>::hun(vs)...); 
} 

int main() 
{ 
    fun(1, 'a', 2.3); 
} 

輸出:

gun(A<Ts...>::hun(vs)...); 
A<int char double >::hun(int) 
A<int char double >::hun(char) 
A<int char double >::hun(double) 

gun(A<Ts...>::hun(vs...)); 
A<int char double >::hun(int char double) 

gun(A<Ts>::hun(vs)...); 
A<int >::hun(int) 
A<char >::hun(char) 
A<double >::hun(double) 
+0

第二個擴展看起來很直接。另外兩個很有趣,但如果用於生產代碼可能會導致混淆。你希望在真實世界的場景中看到這一點嗎? – mark 2012-03-10 23:28:54

+4

我很難說。我猜測我們作爲一個行業可能仍在學習如何使用可變模板。從現在開始幾年後,有人可能會發現一種非常好的方式來使用其他兩種形式,它可能會成爲一種模式。在'98我從來沒有想到我會使用'enable_if'這樣的東西,但我現在一直在做。 C++是一種生機勃勃,成長中的語言! :-) – 2012-03-11 00:42:59

7

例2和3真的是任何形式的涉及可變參數組的代碼很常見。

template<typename... T> 
void f(T&&... t) 
{ 
    // Case 2: 
    auto t2 = std::tuple<T...>(t...); 

    // Case 3: 
    auto t3 = std::make_tuple(std::forward<T>(t)...); 
} 

看着我自己的代碼,我無法找到的情況下1.我可能已經在一些detail命名空間的輔助tempate用它在過去的任何存活的例子,但我不知道。我認爲大多數時候這不會很普遍,甚至是不必要的。

+0

謝謝你的例子 – mark 2012-03-11 07:53:41