Understanding variadic templates
GP and Templates(泛型编程与模板)
现实中许多问题错综而复杂,解决起来极为不易。
人们发现可以将这些问题拆解成更小的问题来进行解决。往往当把问题拆解到最小模块的时候,便能对问题产生新的理解。
能解决问题的根本在于:问题整体可分解为部分,部分可组成为整体,整体等于部分之和。这是还原论的思想,在编程世界叫作分治策略,实现手法分为迭代和递归。
向下拆分,向上总结,就能把一个大问题化为许多小问题,通过解决一个个小问题,最终就能解决整个大问题。
解决之时,需要描述问题的数据和关系。
在C++中,用面向对象来表示事物的整体结构,用数据结构来表示数据之间的关系,用算法来表示具体的逻辑实现。
数据有类型之分,而不同的问题可能本质上实为同类问题,这便导致每次遇到同类问题,还得提供不同类型版本的解法。
因此数据和方法应该进行分离,对数据进行更高层次的抽象。
面向对象编程的目的是将数据和方法关联起来,而为了分离数据和方法之间的依赖,出现了泛型编程。
泛型编程本质上就是对数据类型的高度抽象,使同一个方法能作用到不同的类型,为同类问题提供了一个通解。
C++泛型编程所提供的支持组件便是模板,而Variadic Templates(可变参数模板/可变模板参数),顾名思义,就是支持任意个数、任意类型的模板。
对于一类问题,若发现变化的永远是输入,而解决方法始终不变,便可以使用可变参数模板定义通解。
这个通解,就是问题的「最小模块」,通过迭代或递归,分多次解决分解后的小问题,最终就能解决整个问题。
然而迭代需要持有一个迭代器并改变它,直到某个条件符合。泛型编程发生于编译期,编译期中的整数计算(如enum)或是typedef(using)的类型定义之后就无法进行改变。所以迭代虽然比递归表示起来更加自然,却无法进行实现。
递归符合一切编译期编程的要求,所以可变参数模板由其实现。
由于递归本身的特性,再结合可变参数模板,使得理解起来极为不易。因为你无法看到实际的结果,对于无法看到的东西,理解起来总是比较困难的。
Ellipsis operator and Parameter pack(省略操作符与参数包)
先来看一个简单的可变参数模板示例:
template <class... Args>
void func(Args... args)
{
std::cout << sizeof...(args) << std::endl;
}
...… Continue Reading