c++11可变参数模板的使用1

1.概述

  C++11的新特性--可变模版参数(variadic templates)是C++11新增的最强大的特性之一,它对参数进行了高度泛化,它能表示0到任意个数、任意类型的参数。相比C++98/03,类模版和函数模版中只能含固定数量的模版参数,可变模版参数无疑是一个巨大的改进。然而因为可变模版参数比较抽象,使用起来须要必定的技巧,因此它也是C++11中最难理解和掌握的特性之一。ios

  虽然掌握可变模版参数有必定难度,可是它倒是C++11中最有意思的一个特性,本文但愿带领读者由浅入深的认识和掌握这一特性,同时也会经过一些实例来展现可变参数模版的一些用法。函数

2.可变模版参数的展开

  可变参数模板和普通模板的语义是同样的,只是写法上稍有区别,声明可变参数模板时须要在typename或class后面带上省略号“...”。好比咱们经常这样声明一个可变模版参数:template<typename...>或者template<class...>,一个典型的可变模版参数的定义是这样的:spa

  template<typename... T> void fun(T... args) { }code

上面的可变模版参数的定义当中,省略号的做用有两个:blog

1.声明一个参数包T... args,这个参数包中能够包含0到任意个模板参数;
2.在模板定义的右边,能够将参数包展开成一个一个独立的参数。递归

  上面的参数args前面有省略号,因此它就是一个可变模版参数,咱们把带省略号的参数称为“参数包”,它里面包含了0到N(N>=0)个模版参数。咱们没法直接获取参数包args中的每一个参数的,只能经过展开参数包的方式来获取参数包中的每一个参数,这是使用可变模版参数的一个主要特色,也是最大的难点,即如何展开可变模版参数。博客

  可变模版参数和普通的模版参数语义是一致的,因此能够应用于函数和类,便可变模版参数函数和可变模版参数类,然而,模版函数不支持偏特化,因此可变模版参数函数和可变模版参数类展开可变模版参数的方法还不尽相同,下面咱们来分别看看他们展开可变模版参数的方法。io

 

3.可变模板参数函数

一个简单的可变模版参数函数:模板

template<typename... T>
void fun(T... args)
{
    // 打印参数个数
    cout << sizeof...(args) << endl;  
}

 

上面的例子中,fun()没有传入参数,因此参数包为空,输出的size为0,后面两次调用分别传入两个和三个参数,故输出的size分别为2和3。因为可变模版参数的类型和个数是不固定的,因此咱们能够传任意类型和个数的参数给函数f。这个例子只是简单的将可变模版参数的个数打印出来,若是咱们须要将参数包中的每一个参数打印出来的话就须要经过一些方法了。展开可变模版参数函数的方法通常有两种:一种是经过递归函数来展开参数包,另一种是经过逗号表达式来展开参数包。下面来看看如何用这两种方法来展开参数包。class

3.1递归函数方式展开参数包

经过递归函数展开参数包,须要提供一个参数包展开的函数和一个递归终止函数,递归终止函数正是用来终止递归的,来看看下面的例子。

#include <iostream>
using namespace std;

// 最终递归函数
void print()
{
  cout << "empty" << endl;  
}

// 展开函数
template <typename T, typename... Args>
void print(T head, Args... args)
{
    cout << head << ",";
    print(args...);      
}

int main()
{
    print(1, 2, 3, 4);
    return 0;    
}

上例会输出每个参数,直到为空时输出empty。展开参数包的函数有两个,一个是递归函数,另一个是递归终止函数,参数包Args...在展开的过程当中递归调用本身,每调用一次参数包中的参数就会少一个,直到全部的参数都展开为止,当没有参数时,则调用非模板函数print终止递归过程。

递归调用的过程是这样的:

print(1,2,3,4);print(2,3,4);print(3,4);print(4);print();

上面的递归终止函数还能够写成这样:

template <class T>void print(T t){   cout << t << endl;}

修改递归终止函数后,上例中的调用过程是这样的:

print(1,2,3,4);print(2,3,4);print(3,4);print(4);

当参数包展开到最后一个参数时递归为止。

 

咱们将在下一博客中讲解可变参数模板的其余使用方法。

相关文章
相关标签/搜索