2012-03-10 34 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