C++11:16可变参数模板

可变参数模板

0、课前秀

  • C++11之前,类模板和函数模板只能含有固定数量的模板参数。
  • C++11允许模板定义中包含0到任意多个模板参数,写法上,在typename或class后面带上省略号...
  • 省略号的作用:
    • 在模板定义的右边,可以将参数包展开成一个一个独立的参数。

1、可变参数模板函数

  • 如果需要用参数包中的参数,则一定要将参数包展开。有两种展开参数包的方法
    • (1)通过递归的模板函数来将参数包展开
    • (2)通过逗号表达式和初始化列表方式展开参数包

1.1、可变参数模板函数的定义

template <class... T>
void f(T... args)
{
    cout<<sizeof...(args)<<endl; //打印变参的个数
}
f();//0
f(1,2);//2
f(1,2.5,"");//3

1.2、递归函数方式展开参数包

  • 提供一个参数包展开的函数和一个递归终止函数。
  • 重载的递归终止函数
#include<iostream>
using namespace std;
//递归终止函数
void print() 
{
    cout<<"empty"<<endl;
}
//参数包展开函数
template<class T,class ...Args>
void print(T head, Args... rest)
{
    cout<<"parameter "<<head<<endl;
    print(rest...);
}
int main(void)
{
    print(1,2,3,4);
    return 0;
}
  • 通过type_traits来展开并打印参数包 没写呢

1.3、逗号表达式和初始化列表方式展开参数包

  • 代码
template <class T>
void printarg(T t)
{
    cout<<t<<endl;
}

template <class ...Args>
void expand(Args... args)
{
    int arr[]={(printarg(args),0)...};
}
expand(1,2,3,4);

2、可变参数模板类

  • std::tuple就是一个可变模板类,template <class... Types> class tuple;
  • 可变参数模板类的参数包展开的方式
    • (1)通过模板特化
    • (2)通过继承方式

2.1、模板递归和特化方式展开参数包

2.2、继承方式展开参数包

  • 代码例子
//整型序列的定义
template<int...>
struct IndexSeq{};

//继承方式,开始展开参数包
template<int N, int... Indexs>
struct MakeIndexes:MakeIndexes<N-1,N-1,Indexes...>{};

//模板特化,终止展开参数包的条件
template<int... Indexs>
struct MakeIndexes<0,Indexes...>
{
    typedef IndexSeq<Indexes...>type;
};

int main()
{
    using T = MakeIndexes<3>::type;
    cout<<typeid(T).name()<<endl;
    return 0;
}

3、可变参数模板消除重复代码

  • 1、泛型的打印函数
  • 2、工厂函数

ReadMe

  • 20200506写完半稿,只是初步知道了语法以及应用,但具体怎么用还没有太多概念,还需要再复习一下模板类,模板函数。参考《深入应用C++11》的3.2内容。
原文地址:https://www.cnblogs.com/fewolflion/p/12871268.html