2012-05-03 43 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