可变参数模版

Forums: 

img: 

通常 c 或是 c++ 函数的参数个数和类型都是固定的, 比如 int add(int a, int b); 带有两个 int 的参数 a、 b 。 为了处理传递任意个参数的情况, c 提供了一种方式,比如 printf 的方式。 然而 c 的这种方式是非类型安全的,当 me 们 printf("%d", i); 的时候, 编译器么法去检查 i 是否是整数类型;即使它不是, 这里的调用也是能编译通过的。 c++ 当然还可以使用 c 的技术,然而又提供新的处理方法:可变参数的模板, 也就是模板的参数可以任意多。 实际上 c++ 的可变参数模版和 c 的处理可变参数的某些写法有些类似。

下面是一个 print 的例子, 使用 c++ 书写, 功能就是将传递的参数全部输出。

  1. #include <iostream>
  2. using namespace std ;
  3.  
  4. void print()
  5. {
  6.     return;
  7. }
  8. template <typename T, typename... Tail>
  9. void print(T head, Tail... tail)
  10. {
  11.     cout << head << ' ';
  12.     print(tail...);
  13. }
  14.  
  15. int  main()
  16. {
  17.     print(42, 3.14, "hello,world", 'A');
  18.     return 0;
  19. }

可变参数的模版是 c++11 加入的内容,如果使用 gcc 编译的话,可能要这样编译: $ g++ -std=c++11 hello.cpp 。

c 处理可变长度的参数

前面说了, c 也可以处理可变长度的参数, 比如 printf 的参数个数就是可变的, printf("hello,world"); 可以, printf("hello, %d %s", 42, "ant"); 可以。 下面是 c 处理可变参数的方法:

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3.  
  4. // 计算 n 个数的和
  5. int add(int n, ...)
  6. {
  7.     int i, sum, tmp;
  8.     va_list arg;    // 一种“莫名”的类型
  9.    
  10.     va_start(arg, n);    // 初始化, n 是最后一个可见参数的名字
  11.     for(sum = i = 0; i < n; ++i){
  12.         tmp = va_arg(arg, int);    // 获取一个参数的值, int 是类型
  13.         sum += tmp;
  14.     }
  15.     va_end(arg);    // end
  16.     return sum;
  17. }
  18.  
  19. int main()
  20. {
  21.     printf("%d\n", add(4, 1, 2, 3, 4));
  22.     printf("%d\n", add(10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
  23.    
  24.     return 0;
  25. }

精诚所至,金石为开