【模板进阶】类模板中可变参的特殊继承方式

本篇博客主要介绍在类模板中可变参数的特殊继承方式和展开方式。 回顾之前的可变参展开:可变参模板


一、父类

首先,我们有一个父类,是一个可变参类模板,如下:

//父类
template<typename...Args>
class myclass {
public:
	myclass() {
		std::cout << "myclass::myclass()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}
};

下面我们开始对它的特殊继承进行讨论。


二、 m y c l a s s < A r g . . . > myclass<Arg...> myclass<Arg...>继承

参考下方代码:

//myclass<Args...>继承
template<typename... Args>
class myclass2 :public myclass<Args...> {
public:
	myclass2() {
		std::cout << "myclass2::myclass2()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}

};

像这样的继承方式,在参数范围上与父类一样。例如,下面的代码:

myclass2<double, float, int> myc2;

将会实例化出一个 m y c l a s s < d o u b l e , f l o a t , i n t > myclass<double,float,int> myclass<double,float,int>的父类和 m y c l a s s 2 < d o u b l e , f l o a t , i n t > myclass2<double,float,int> myclass2<double,float,int>的子类。调用结果如下:

在这里插入图片描述


三、 m y c l a s s < A r g > . . . myclass<Arg>... myclass<Arg>...继承

这样的继承方式可以看做是多继承,具体上,这是继承的一个基类参数包,可以参考:基类参数包的展开这篇博客,讲的比较清晰。

由于是多继承,那自然会实例化出多个父类。比如下面的代码:

//myclass<Args>..继承
template<typename... Args>
class myclass3 :public myclass<Args>...{
public:
	myclass3() {
		std::cout << "myclass3::myclass3()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}
};


这里会实例化出 m y c l a s s < d o u b l e > , m y c l a s s < f l o a t > , m y c l a s s < i n t > myclass<double>,myclass<float>,myclass<int> myclass<double>,myclass<float>,myclass<int>三个父类模板,通过递归的方式逐步展开

myclass3<double, float, int> myc3;

可以发现,实例化出了三个父类模板,和一个子类模板:

在这里插入图片描述


四、 m y c l a s s < A r g , c h a r > . . . myclass<Arg,char>... myclass<Arg,char>...继承

这种继承方式和上一中类似,只不过指定了增加一个 c h a r char char类型的参数,同样会实例化出多个父类模板。
参考下面的代码:

//myclass<Arg,char>继承
template<typename... Args>
class myclass4 :public myclass<Args, char>...{
public:
	myclass4() {
		std::cout << "myclass4::myclass4()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}

};

这将实例化出 m y c l a s s < d o u b l e , c h a r > , m y c l a s s < f l o a t , c h a r > , m y c l a s s < i n t , c h a r > myclass<double,char>,myclass<float,char>,myclass<int,char> myclass<double,char>,myclass<float,char>,myclass<int,char>三个父类,和 m y c l a s s 4 < d o u b l e , f l o a t , i n t , c h a r > myclass4<double,float,int,char> myclass4<double,float,int,char>的一个子类。

myclass4<double, float, int> myc4;

在这里插入图片描述
这里显示可变参数为 3 3 3不包括 c h a r char char类型,因为它不属于可变参数里面,所以实际上这里还是四个参数。


五、 m y c l a s s < A r g s , A r g s . . . > . . . myclass<Args,Args...>... myclass<Args,Args...>...继承

这种继承方式,前一个参数是 A r g s Args Args只有一个参数,而后一个参数 A r g s . . . Args... Args...是一个参数包,而最后又用一个 . . . ... ...表示继承的是参数包,因此这里会实例化出多个父类。

//myclass<Args,Args...>...继承
template<typename... Args>
class myclass5 :public myclass<Args, Args...>...{
public:
	myclass5() {
		std::cout << "myclass5::myclass5()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}

};

下方的代码将实例化出 m y c l a s s < d o u b l e , d o u b l e , f l o a t , i n t > , m y c l a s s < f l o a t , d o u b l e , f l o a t , i n t > , m y c l a s s < i n t , d o u b l e , f l o a t , i n t > myclass<double,double,float,int>,myclass<float,double,float,int>,myclass<int,double,float,int> myclass<double,double,float,int>,myclass<float,double,float,int>,myclass<int,double,float,int>这个三个父类,和 m y c l a s s 5 < d o u b l e , f l o a t , i n t > myclass5<double,float,int> myclass5<double,float,int>这个子类

myclass5<double, float, int> myc5;

运行结果:

在这里插入图片描述


六、 m y c l a s s < A r g . . . , A r g . . . > myclass<Arg...,Arg...> myclass<Arg...,Arg...>继承

与第一种继承类似,只不过把参数列表复制了一遍。参考下方代码:


//myclass<Args...,Args...>继承
template<typename... Args>
class myclass6 :public myclass<Args..., Args...> {
public:
	myclass6() {
		std::cout << "myclass6::myclass6()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}
};

这将实例化出 m y c l a s s < d o u b l e , f l o a t , i n t , d o u b l e , f l o a t , i n t > myclass<double,float,int,double,float,int> myclass<double,float,int,double,float,int>六个参数的父类。

myclass6<double, float, int> myc6;

如图:

在这里插入图片描述


七、 m y c l a s s < A r g , A r g > . . . myclass<Arg,Arg>... myclass<Arg,Arg>...继承

这种继承方法和 m y c l a s s < A r g > . . . myclass<Arg>... myclass<Arg>...类似,只不过是实例化出的模板参数复制了一遍,同样也是多继承。参考下方代码:

//myclass<Args,Args,Args...>...继承
template<typename... Args>
class myclass9 :public myclass<Args,Args>...{
public:
	myclass9() {
		std::cout << "myclass9::myclass9()执行了,可变参个数为:" << sizeof...(Args) << "\n";
	}

};

这将实例化出 m y c l a s s < d o u b l e , d o u b l e > , m y c l a s s < f l o a t , f l o a t > , m y c l a s s < i n t , i n t > myclass<double,double>,myclass<float,float>,myclass<int,int> myclass<double,double>,myclass<float,float>,myclass<int,int>这个三个父类。

myclass9<double, float, int> myc9;

如下图:

在这里插入图片描述


八、总结:

对于可变参类模板的继承方式总结起来就两种,其他方式可以看做是这两种方式的排列组合。

( 1 ) (1) (1)形如 t e m p l a t e < A r g s . . . > template<Args...> template<Args...>的单继承

( 2 ) (2) (2)形如 t e m p l a t e < A r g s > . . . template<Args>... template<Args>...的多继承


继承的时候可以对这两种类型进行排列组合,也可以指定增加其中一个类型,如 c h a r char char类型等。
注意, t e m p l a t e < A r g s . . . > template<Args...> template<Args...>可以有多个,而 t e m p l a t e < A r g s > . . . template<Args>... template<Args>...只能有一个。

即如下的是合法的:
t e m p l a t e < A r g s , A r g s . . . , A r g s . . . , A r g s . . . > . . . template<Args,Args...,Args...,Args...>... template<Args,Args...,Args...,Args...>...

而多继承一定要配合 A r g s Args Args来使用,即 t e m p l a t e < A r g s . . . > . . . template<Args...>... template<Args...>...是非法的!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值