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 的方式定义。 这样做会让模板名因为模板嵌套变得很长,可读性降低。