Typelists是一个用来操作一大群型别的C++工具。就像lists对数值提供各种基本操作一样,typelists对型别也提供相同的操作。
比如有时候必须对某些型别重复撰写相同的代码,但是template又帮不上忙。假设需要实作一个Abstract Factory,像如下这样:
cpp
class AbstractFactory {
public:
virtual Window* createWindow() = 0;
virtual Button* createButton() = 0;
virtual ScrollBar* createScrollBar() = 0;
// ......
};
如果想将以上AbstractFactory的概念特化,并纳入程序库中,你必须让使用者得以产生针对任意性别的工厂,但是template无法支持这一特性。此时Typelists可以帮助AbstractFactory泛化成功。
Typelists的定义
Typelists是一个编译期的类型链表,该功能在c++11/17中已经有std::tuple支持,std::tuple的底层实现就是TypeList。定义如下:
cpp
template<typename T, typename U>
struct TypeList {
typedef T Head;
typedef U Tail;
}
说明:
T:当前节点存储的类型
U:当前节点的后继节点。该节点有两种情况,一种情况是TypeList<...>类型(链表的下一个节点),另一个情况是标记一种类型,即代表链表的尾部。
typedef T Head; 代表当前节点存储大的类型;
typedef U Tail; 代表下一节点,即列表的剩余部分。
比如定义一个嵌套实例化的链表:typedef TypeList<int, TypeList<double, TypeList<std::string, void>>> MyTyppes;中,Head代表int,Tail代表TypeList<double, TypeList<std::string, void>>
按索引访问
按索引访问定义如下:
cpp
template<typename TList, unsigned int index>
struct TypeAt;
template<class Head, class Tail>
struct TypeAt<TypeList<Head, Tail>, 0> {
typedef Head Result;
};
template<class Head, class Tail, unsigned int index>
struct TypeAt<TypeList<Head, Tail>, index> {
typedef typename TypeAt<Tail, index-1>::Result Result;
}
说明:
首先声明主模板,再通过模板的特化实现具体逻辑。
实现模版的全特化作为递归的终止条件,即当index=0时,获得的类型为Head存储的对应类型;
实现模板的偏特化作为递归的递归逻辑,进行模板的逻辑推倒,即跳过列表的头部元素,去剩余的类型中找第index-1个类型,依次类推,直到index变成0.
typename是一种语法要求,声明访问的是类型。访问嵌套模板时,必须用typename声明是类型
举个例子:比如需要访问上面定义的MyTypes中下表为2的类型,推倒过程如下:
- TypeAt<MyTypes, 2>::Result
- => TypeAt<TypeList<int, TypeList<double, TypeList<std::string, void>>>, 2>::Result
- => TypeAt<TypeList<double, TypeList<std::string, void>>, 1>::Result
- => TypeAt<TypeList<std::string, void>, 0>::Result;
- => std::string
查找typelists的类型
定义:
cpp
struct NullType;
template<typename TList, typename T>
struct IndexOf;
template<typename T>
struct IndexOf<NullType, T> {
enum { value = -1 };
};
template<typename Tail, typename T>
struct IndexOf<TypeList<T, Tail>, T> {
enum { value = 0 };
};
template<typename Head, typename Tail, typename T>
struct IndexOf<TypeList<Head, Tail>, T> {
private:
enum { temp = IndexOf<Tail, T>::value };
public:
enum { value = (temp == -1 ? -1 : 1 + temp) };
};
说明:
首先声明主模板,再通过模板特化实现具体逻辑
递归终止条件1:当TypeList为NullType时,说明查找失败,value为-1
递归终止条件2:当Head类型为T时,说明找到了,返回0
递归逻辑推倒:去除当前节点类型,在剩余的节点中查找,查找结果递增。
举个例子,还是以MyTypes为例,查找std::string类型:
- IndexOf<TypeList<int, TypeList<double, TypeList<std::string, NullType>>>, std::string>::value
- 头类型int =/ std::string, 进行递归:1 + IndexOf<TypeList<double, TypeList<std::string, NullType>>, std::string>::value
- 头类型double=/ std::string,继续进行递归:1 + 1 + IndexOf<TypeList<std::string, NullType>, std::string>::value
- 头类型std::string==std::string,找到,结束递归,value=1+1+0=2
列表中添加新的类型
定义如下:
cpp
template<typename TList, typename T>
struct Append;
template<>
struct Append<NullType, NullType> {
typedef NullType Result;
};
template<typename T>
struct Append<NullType, T> {
typedef TypeList<T, NullType> Result;
};
template<typename Head, typename Tail>
struct Append<NullType, TypeList<Head, Tail>> {
typedef TypeList<Head, Tail> Result;
};
template<typename Head, typename Tail, typename T>
struct Append<TypeList<Head, Tail>, T> {
typedef TypeList<Head, typename Append<Tail, T>::Result> Result;
};
移除列表中的某个元素
定义如下:
cpp
template<typename TList, typename T>
struct Erase;
template<typename T>
struct Erase<NullType, T> {
typedef NullType Result;
};
template<typename Tail, typename T>
struct Erase<TypeList<T, Tail>, T> {
typedef Tail Result;
};
template<typename Head, typename Tail, typename T>
struct Erase<TypeList<Head, Tail>, T> {
typedef typename TypeList<Head, typename Erase<Tail, T>::Result> Result;
};
template<typename TList, typename T>
struct EraseAll;
template<typename T>
struct EraseAll<NullType, T> {
typedef NullType Result;
};
template<typename T, typename Tail>
struct EraseAll<TypeList<T, Tail>, T> {
typedef typename EraseAll<Tail, T>::Result Result;
};
template<typename Head, typename Tail, typename T>
struct EraseAll<TypeList<Head, Tail>, T> {
typedef typename TypeList<Head, typename EraseAll<Tail, T>::Result> Result;
};
删除重复元素
定义如下:
cpp
template<typename TList>
struct NoDuplicate;
template<>
struct NoDuplicate<NullType> {
typedef NullType Result;
};
template<typename Head, typename Tail>
struct NoDuplicate<TypeList<Head, Tail>> {
private:
typedef typename NoDuplicate<Tail>::Result L1;
typedef typename Erase<L1, Head>::Result L2;
public:
typedef typename TypeList<Head, L2> Result;
};
取代TypeList中的某个元素
定义如下:
cpp
template<typename TList, typename T, typename U>
struct Replace;
template<typename T, typename U>
struct Replace<NullType, T, U> {
typedef NullType Result;
};
template<typename Tail, typename T, typename U>
struct Replace<TypeList<T, Tail>, T, U> {
typedef TypeList<U, Tail> Result;
};
template<typename Head, typename Tail, typename T, typename U>
struct Replace<TypeList<Head, Tail>, T, U> {
typedef typename Replace<TypeList<Tail>, T, U>::Result Temp;
typedef typename TypeList<Head, Temp> Result;
};
长度获取
定义如下:
cpp
template<typename TList>
struct Length;
template<>
struct Length<NullType> {
enum { value = 0 };
};
template<typename Head, typename Tail>
struct Length<TypeList<Head, Tail>> {
enum {
value = 1 + Length<Tail>::value
};
};