(C++模板编程):通过递归继承方式展开类型、非类型、模板模板参数包

目录

可变参类模板

通过递归继承方式展开类型、非类型、模板模板参数包

类型模板参数包的展开,此范例取材于C++标准库中的tuple(元组)

非类型模板参数包展开示例

模板模板参数包的展开示例

可变参类模板

  • 允许模板定义中包含0到多个(任意个)模板参数

通过递归继承方式展开类型、非类型、模板模板参数包

类型模板参数包的展开,此范例取材于C++标准库中的tuple(元组)

//主模板定义(泛化版本的类模板)
template <typename ...Args>
class myclasst
{
public:
	myclasst()
	{
		printf("myclasst::myclasst()泛化版本执行了,this = %p\n", this);
	}

};

///template <typename ...Args>class myclasst; //主模板声明(前向声明/前置声明)

template <typename First,typename ... Others>
class myclasst<First, Others...> :private myclasst<Others...> //偏特化
{
public:
	myclasst() :m_i(0)
	{
		printf("myclasst::myclasst()偏特化版本执行了,this = %p,sizeof...(Others)=%d\n", this, sizeof...(Others));
	}

	First m_i;
};
  • 有时只写类模板声明而不写类模板定义的手法非常重要,靠这种手段能够帮助程序员排错。
    • template <typename ...Args>class myclasst;      主模板声明(前向声明/前置声明)
  • 调用
myclasst<int, float, double> myc;
  • 输出

  • 分析,实例化顺序:

提供template<> 特化版本,则不通过泛化版本去实例化myclasst<>类型

//主模板定义(泛化版本的类模板)
template <typename ...Args>
class myclasst
{
public:
	myclasst()
	{
		printf("myclasst::myclasst()泛化版本执行了,this = %p\n", this);
	}

};

///template <typename ...Args>class myclasst; //主模板声明(前向声明/前置声明)

template <typename First,typename ... Others>
class myclasst<First, Others...> :private myclasst<Others...> //偏特化
{
public:
	myclasst() :m_i(0)
	{
		printf("myclasst::myclasst()偏特化版本执行了,this = %p,sizeof...(Others)=%d\n", this, sizeof...(Others));
	}

	First m_i;
};

template<> 
class myclasst<> //一个特殊的特化版本,看起来象全特化,不是全特化,可变参模板不存在全特化
{
public:
	myclasst()
	{
		printf("myclasst::myclasst()特殊的特化版本执行了,this = %p\n", this);
	}
};
  • 通过myclasst<int, float, double> myc;调用,输出如下

  • 优先使用实例化的template<>  class myclasst<> 特殊版本。

带参数的构造函数

template <typename First,typename ... Others>
class myclasst<First, Others...> :private myclasst<Others...> //偏特化,注意是private继承方式
{
public:
	myclasst() :m_i(0)
	{
		printf("myclasst::myclasst()偏特化版本执行了,this = %p,sizeof...(Others)=%d\n", this, sizeof...(Others));
	}

	myclasst(First parf, Others... paro) :m_i(parf), myclasst<Others...>(paro...)
	{
		cout << "---------------------begin-----------------" << endl;
		printf("myclasst::myclasst(parf,...paro)执行了,this = %p\n", this);
		cout << "m_i = " << m_i << endl;
		cout << "---------------------end-----------------" << endl;
	}


	First m_i;
};
  • 调用
myclasst<int, float, double> myc(12,13.5,23);
  • 输出

泛化版本可变参数书写注意事项

template <typename ...Args1,typename ... Args2>
class myclasst2 {};
//或者
template <typename ...Args, typename U>
class myclasst3 {};
  • 针对泛化版本,可变参数必须放置在末尾,否则报错

非类型模板参数包展开示例

//主模板定义(泛化版本的类模板)
template <int ...FTArgs> //int 替换为auto也可以
class myclasst2
{
public:
	myclasst2()
	{
		printf("myclasst2::myclasst2()泛化版本执行了,this = %p\n", this);
	}
};
template <int First,int ...Others> //int替换成auto也没问题
class myclasst2<First, Others...> :private myclasst2<Others...> //偏特化
{
public:
	myclasst2()
	{
		printf("myclasst2::myclasst2()偏特化版本执行了,this = %p,sizeof...(Others)=%d,First=%d\n", this, sizeof...(Others),First);
	}
};
  • 调用
myclasst2<12, 18, 23> myc2;
  • 输出

模板模板参数包的展开示例

//泛化版本
template<typename T, 
		template<typename> typename... Container>
class ParentMM
{
public:
	ParentMM()
	{
		printf("ParentMM::ParentMM()泛化版本执行了,this = %p\n", this);
	}
};

template<typename T,
	template<typename> typename FirstContainer,
	template<typename> typename... OtherContainers>
class ParentMM<T, FirstContainer, OtherContainers...> :private ParentMM<T, OtherContainers...> //偏特化
{
public:
	ParentMM()
	{
		printf("ParentMM::ParentMM()偏特化版本执行了,this = %p,sizeof...(OtherContainers)=%d\n", this, sizeof...(OtherContainers));
		m_container.push_back(12);
	}

	FirstContainer<T>  m_container;
};

template<typename T,
	template<typename> typename... Container>
class myclasst3 :private ParentMM<T, Container...>
{
public:
	myclasst3()
	{
		printf("myclasst3::myclasst3()执行了,this = %p,T的类型是:%s,Container参数个数是%d个\n",
			this,
			typeid(T).name(), //以后会用boost库中的type_id_with_cvr<.......>().pretty_name()。
			sizeof...(Container));
	}
};
  • 【注】关于理解template<typename> typename... Container,联想到模板类声明
  • template<typename T>
    class Container;
    • 将模板类Container视为类型,再结合可变参数定义typename ... T
template<typename> 
typename... Container
  • 调用
myclasst3<int, vector, list, deque> myc3;
  • 输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值