C++0x 学习笔记之 Variadic Templates

http://feng.free.lc/?p=28
Variadic Templates 的引入,消去了烦冗的模板特化。 一个例子:
#include double do_sum() { return 0; } template< typename T, typename... Args > double do_sum( T&& t, Args&& ... args ) { return t + do_sum( args... ); } int main() { std::cout << do_sum( 1.0, 2.0, 3.0, 4.0 ) << std::endl; return 0; }
这里需要注意的有两点:
  • double do_sum() 这个函数必须在变长模板函数 double do_sum( T&& t, Args&& ... args ) 之前声明
  • 变长模板函数实现中必须使用另外一个函数递归实现
另外要看到,在变长模板函数声明中使用 ... 的方法
  • 模板上用的是 template< typename... Args>
  • 函数参数中用的是 double do_sum(Arg ... arg)
  • 函数体中用的是 do_sum(arg...)
大致可以看出,有 typename 的时候 .. 跟 typename 后边,否则跟在 Arg 后边,最后则是在参数 arg 后边
如果需要知道到底传入了多少个参数可以这样来
template std::size_t how_many_args(Args ... args) { return sizeof...(args); }
variadic template 基本使用到这里就差不多了,下边的内容略略而过即可
再次注意这个 ...,来个稍微有点复杂的
template void f(T (* ...t)(int, int)); int add(int, int); float subtract(int, int); void g() { f(add, subtract); }
再来一个多继承 template class X : public Mixins... { public: X(const Mixins&... mixins) : Mixins(mixins)... { } };
整数也是可以放在 variadic template 上的 template class Tuple; // Types is a template type parameter pack template struct multi array; // Dims is a non-type template parameter pack
缺省template参数也是可以的,比如 template class String; String<>* p; // OK: String String* q; // syntax error template class Tuple; Tuple<>* t; // OK: Elements is empty Tuple* u; // syntax error
还有 template template 的这种 template class A { /* ... */ }; template class B { /* ... */ }; template class C { /* ... */ }; template class P> class X { /* ... */ }; template class Q> class Y { /* ... */ }; X xa; // okay X xb; // ill-formed: default arguments for the parameters of a template template argument are ignored X xc; // ill-formed: a template parameter pack does not match a template parameter Y ya; // ill-formed: a template parameter pack does not match a template parameter Y yb; // ill-formed: a template parameter pack does not match a template parameter Y yc; // okay
也特别注意 Y 和 X 无论哪个都不能通过。这是因为在 template 中,模板类型顺序是不可以搞错的,比如: template struct A { void f1(); void f2(); }; template void A::f1() { } // OK template void A::f2() { } // erro
于是同样就有 template struct B { void f3(); void f4(); }; template void B::f3() { } // OK
更详细的有 template X f(Y); template X g(Y); int i = f(5.6); // Y is deduced to be double int j = f(5.6); // ill-formed: X cannot be deduced f(f); // Y for outer f deduced to be // int (*)(bool) f(f); // ill-formed: f does not denote a // single function template specialization int k = g(5.6); // Y is deduced to be double, Z is deduced to an empty sequence f(g); // Y for outer f deduced to be // int (*)(bool), Z is deduced to an empty sequence
注意这种特化 template struct Tuple { }; template void g(Tuple); // #1 template void g(Tuple); // #2 template void g(Tuple); // #3 g(Tuple<>()); // calls #1 g(Tuple()); // calls #2 g(Tuple()); // calls #3 g(Tuple()); // calls #3
还有多个 variadic template 嵌套着用的 template struct Tuple {}; template struct Pair {}; template struct zip { template struct with { typedef Tuple...> type; }; }; typedef zip::with::type T1; // T1 is Tuple, Pair > typedef zip::with::type T2; // error: different number of arguments specified // for Args1 and Args2 template void g(Args... args) { f(const cast(&args)...); // okay: ‘‘Args’’ and ‘‘args’’ are expanded f(5 ...); // error: pattern does not contain any parameter packs f(args); // error: parameter pack ”args” is not expanded f(h(args...) + args...); // okay: first ‘‘args’’ expanded within h, second ‘‘args’’ expanded within f. }
再举一个完整的例子: template void print_comma_separated_list(T&& value) { std::cout< void print_comma_separated_list(First&& first,Rest&& ... rest) { std::cout< 特别说明: 本文例程多摘自 c++0x N2242,这里可以找到: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2242.pdf
Tags: 

延伸阅读

最新评论

发表评论