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

目录

可变参类模板

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

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

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

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

可变参类模板

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

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

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

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

};

///template class myclasst; //主模板声明(前向声明/前置声明)

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

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

  • 分析,实例化顺序:

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

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

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

};

///template class myclasst; //主模板声明(前向声明/前置声明)

template 
class myclasst :private myclasst //偏特化
{
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 myc;调用,输出如下

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

带参数的构造函数

template 
class myclasst :private myclasst //偏特化,注意是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(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 myc(12,13.5,23);
  • 输出

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

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

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

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

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

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

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

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

	FirstContainer  m_container;
};

template typename... Container>
class myclasst3 :private ParentMM
{
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... Container,联想到模板类声明
  • template
    class Container;
    • 将模板类Container视为类型,再结合可变参数定义typename ... T
template 
typename... Container
  • 调用
myclasst3 myc3;
  • 输出

你可能感兴趣的:(#,C++模板编程)