c++泛型编程之Typelists

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的类型,推倒过程如下:

  1. TypeAt<MyTypes, 2>::Result
  2. => TypeAt<TypeList<int, TypeList<double, TypeList<std::string, void>>>, 2>::Result
  3. => TypeAt<TypeList<double, TypeList<std::string, void>>, 1>::Result
  4. => TypeAt<TypeList<std::string, void>, 0>::Result;
  5. => 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类型:

  1. IndexOf<TypeList<int, TypeList<double, TypeList<std::string, NullType>>>, std::string>::value
  2. 头类型int =/ std::string, 进行递归:1 + IndexOf<TypeList<double, TypeList<std::string, NullType>>, std::string>::value
  3. 头类型double=/ std::string,继续进行递归:1 + 1 + IndexOf<TypeList<std::string, NullType>, std::string>::value
  4. 头类型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
    };
};
相关推荐
KoiHeng3 分钟前
Java的文件知识与IO操作
java·开发语言
-Try hard-10 分钟前
完全二叉树、非完全二叉树、哈希表的创建与遍历
开发语言·算法·vim·散列表
霍理迪17 分钟前
JS作用域与预解析
开发语言·前端·javascript
Traced back21 分钟前
# C# WinForms 数据库清理系统基础知识与避坑指南
开发语言·数据库·c#
煜磊21 分钟前
MD5加盐值-注册与登录
java·开发语言
茉莉玫瑰花茶31 分钟前
C++ 17 详细特性解析(4)
开发语言·c++·算法
rosmis41 分钟前
地铁病害检测系统软件改进记录-2-02
开发语言·前端·javascript
欧阳x天1 小时前
STL详解(九)—— stack和queue的模拟实现
开发语言·c++
xqqxqxxq1 小时前
洛谷算法1-1 模拟与高精度(NOIP经典真题解析)java(持续更新)
java·开发语言·算法
沐知全栈开发1 小时前
Rust 函数
开发语言