C++ 可变模板参数初探

参考:泛化之美–C++11可变模版参数的妙用
根据参考资料,简单验证了一下模板函数、模板类中总共4种情况。
4种情况的详细讲解直接看参考资料吧,大佬写的非常好,在这里本人就不瞎说了。

#include <iostream>

//用哪个就取消相应注释
#define func_recursion // 可变模板参数函数——递归法
//#define func_comma     // 可变模板参数函数——逗号表达式法

//#define class_recursion // 可变模板参数类——递归法
//#define class_inherit   // 可变模板参数类——继承法

/****************可变模板参数函数*********************/
/* 可变模板参数函数——递归法 */
#ifdef func_recursion 
/*
* 终止递归,当参数只剩下一个时,就调用这个重载版本
*/
template<typename last_type>
void outprint(last_type t) { std::cout << t << std::endl; }

/*
* ...放在什么后面,就代表什么被展开
* typename...表示还有多个typename需要被展开,rest_types代表了这些typename的集合
* rest_types...表示rest_types需要被展开,datas是这些类型对应量的集合
* datas...表示将量的集合展开,调用合适的outprint()的重载版本
*/
template<typename first_type,typename...rest_types>
void outprint(first_type t, rest_types...datas) {
    std::cout << t << std::endl;
    outprint(datas...);
}
#endif

/* 可变模板参数函数——逗号表达式法 */
#ifdef func_comma
/*
* outp()不再是递归终止函数,只是用来处理参数集合展开后的某一个元素
*/
template<typename last_type>
void outp(last_type t) { std::cout << t << std::endl; }

/*
* 逗号表达式从左到右顺序执行,最终表达式的值为最右子式的值。
* 这里temp数组最终结果是int temp[sizeof(datas)],元素均为0。利用temp数组的创建过程来附带展开datas。
* 通过“列表初始化”初始化一个变长数组temp,
* 将整体(outp(datas),0)展开成一系列子式:(outp(datas1),0),(outp(datas2),0),(outp(datas3),0),...
* outp(datas)中datas并不在这个()里展开,而是(outp(datas),0)整个展开,因此datas后不加...,而是在()后加...
*/
template<typename...rest_types>
void outprint(rest_types...datas) {
    int temp[] = {(outp(datas),0)...};
}
#endif

/****************可变模板参数类*********************/
/* 可变模板参数类——递归法 */
#ifdef class_recursion

/*
* 第1部分:定义类型数量≥1的模板类,除了第一个类型,其余的用可变参数rest_types表示
* 当类型数量大于1时,每次把第一个取出,把剩下的类型集合rest_types展开后递归
*/
template <typename first_type,typename... rest_types>
class type_show{
public:
    static void print_type() {
        first_type temp;
        std::cout << typeid(temp).name() << std::endl;
        type_show<rest_types...>::print_type();
    }
};

/*
* 第2部分:特化的终止递归类
*/
template <typename last_type>
class type_show<last_type> {
public:
    static void print_type() {
        last_type temp;
        std::cout << typeid(temp).name() << std::endl;
    }
};

#endif

/* 可变模板参数类——继承法 */
#ifdef class_inherit

/*
* 和可变模板参数函数——递归法类似,通过递归继承实现递归调用函数的效果
*/
template <typename first,typename... rest_types>
class type_show :public type_show<rest_types...>{
public:
    type_show() {
        first temp;
        std::cout << typeid(temp).name() << std::endl; // 在构造函数中输出被展开的类型名
    }
};

/*
* 特化的模板类,递归继承的终点
*/
template <typename last_types>
class type_show<last_types> {
public:
    type_show() {
        last_types temp;
        std::cout << typeid(temp).name() << std::endl;
    }
};

#endif

int main()
{

#if (defined func_recursion) || (defined func_comma)
    outprint(1, 2, 3, "1234");
#endif

#ifdef class_recursion
    type_show<int, double, short>::print_type();
#endif

#ifdef class_inherit
    // 连续继承时构造函数的执行顺序是倒着的
    type_show<int, double, short> temp;
#endif


    system("pause");
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值