Variadic Templates

一、可变参函数模板

/*********************可变参数函数模板**********************/
template<typename... T> //T:一包类型 ,args: 一包形参
void myfunc(T... args)
{
    cout << "可变参数 函数 模板" << endl;
    cout << sizeof...(args) << endl;
    cout << sizeof...(T) << endl;
}
  • 注意这三个点(…)出现的位置。在具体的函数形参中,出现在了类型名的后面(Eg:T…)。但如果这个类型后面有引用,则出现在引用的后面(Eg: T&…)。具体示例如下。
template<typename T,typename... U>
void myfunc1(const T& firstarg, const U&... othetarg)
{
    cout << "含有一个非变参的类型typename T,typename... U" << endl;
    //cout << sizeof...(firstarg) << endl;  //sizeof...只能用在一包类型或一包形参上
    cout << sizeof...(othetarg) << endl;
}
函数包的展开

函数包的展开会利用与函数模板一样的同名函数,来作为终止条件,此函数需要注意的是参数为空。
递归函数的方式展开函数包,对于函数模板也有一般的形式要求。

  1. 带一个单独的参数;
  2. 后面跟一个“一包参数”;
/*********************参数包的展开(递归函数的方式展开)**********************/
//先写一个函数模板的同名函数,作为展开的终止函数,此函数 的形参要为0
void display_args()
{
    cout << "执行了终止函数" << endl;
}
template<typename T,typename... U>
void display_args(const T& firstarg, const U&... otherargs)
{
    cout << firstarg << endl;
    display_args(otherargs...); //注意传进来的是一包形参,这里的...不能省略
}
  • 因为参数是一个个被剥离,到最后一次的时候参数为空,而函数模板的参数至少为一个,当参数为空的时候会调用与函数模板同名的函数,来作为递归的终止条件。

二、可变参类模板

在类的模板中先有泛化后有特化。可变参类模板的用途一般定位为中高级应用。

/*********************可变参数类模板**********************/
//泛化版本的模板(现有泛化才有特化)
template<typename... Args>
class MyClass
{
public:
    MyClass() 
    {
        printf("MyClass::MyClass()泛化版本执行了,this = %p\r\n", this);
    }
};
///*****************************当增加了一个特殊的特化类模板会被先执行(当和泛化类模板共存时)******************************************************/
//template<>
//class MyClass<>
//{
//public:
//    MyClass()
//    {
//        printf("MyClass::MyClass()特殊的特化版本执行了,this = %p\r\n", this);
//    }
//};
///***********************************************************************************/

//可变参类模板
template<typename First,typename...Others> 
class MyClass<First,Others...>: private MyClass<Others...>      //先执行父类的构造函数,后执行子类的构造函数
{
public:
    MyClass() :m_i(0)
    {
        printf("MyClass::MyClass()偏特化版本执行了,this = %p, sizeof...(Others) = %d\r\n", this, sizeof...(Others));
    }
    //增加一个有参数的构造函数
    MyClass(First parf, Others... paro):m_i(parf),MyClass<Others...>(paro...)   //注意此处第二个参数的写法
    {
        cout << "-------------------begin--------------------" << endl;
        printf("MyClass::MyClass(parf,...paro)执行了,this = %p\n", this);
        cout << "m_i = " << m_i << endl;
        cout << "--------------------end---------------------" << endl;
    }
    First m_i;
};

这是通过递归的方式展开参数包。类似于函数模板的展开,在递归继承的时候,参数为空就会停止类模板的继承,进而实例化一个泛化版本的类。具体的层次关系如下。

可变参类模板递归继承方式层次关系
在类的实例化中先执行的是父类的构造函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值