CTTCG 24 Typelists
本章介绍了构建类型列表的技巧。既然类型列表可以使用这类技巧,值列表当然也可以在编译期完成类似的计算。
类型列表一开始是用可变长参数列表定义的。
template <typename... Elements>
class Typelist {};
很容易使用偏特化手段为 Typelist 定义 Front trait,以此获得列表的第一个元素。当然这要求类型列表非空,否则不能完成实例化。
类似地,可以定义下面一系列操作:
PopFront
:获得列表去掉第一个元素的剩余列表PushFront
:为列表前面添加一个元素得到新的列表Back
:获得最后一个元素PopBack
:去掉最后一个元素的剩余列表PushBack
:为列表后面添加一个元素得到新的列表IsEmpty
:检查列表是否为空,这将被用来进行派发操作,比如:template<typename List, bool Empty = IsEmpty<List>::value> class LargestTypeT;
作为原始模板,不提供定义。然后分别为两种情况提供偏特化定义。Transform
:使用一个类模板作为参数,用这个类模板将列表中的每个类型进行类型转换。这可以用递归实现,也能使用更高效的折叠表达式实现。NthElement
:递归去掉列表的头 N 个元素,新列表的第 0 个元素就是要找的元素。Select
:通过下标列表和 NthElement,使用折叠表达式和拼接操作,选出类型列表的子序列。InsertionSort
:取下列表的第 0 个元素,和列表的第 1 个元素进行比较,决定拼接和排序的顺序。
非类型列表:将数值信息作为参数嵌入到类型中。比如:CTValue<int, 2>
中携带了类型和常量数字 2。
在变长参数模板出现之前,类型列表通常使用 Lisp Cons
的方式定义。 这样做会让模板名因为模板嵌套变得很长,可读性降低。