C++模板编程——typelist的实现

文章最后给出了汇总的代码,可直接运行

1. typelist是什么

typelist是一种用来操作类型的容器。和我们所熟知的vector、list、deque类似,只不过typelist存储的不是变量,而是类型。

typelist简单来说就是一个类型容器,能够提供一系列的操作。

本文将展示使用元编程实现typelist。

2. 要实现的typelist的接口

在此列举一下即将要编写的typelist的所有接口:

  • typelist:要实现的容器类型。
  • front<typelist>:获取容器中的第一个元素。
  • size<typelist>:获取容器的元素数量。
  • pop_front<typelist, elem>:移出第一个元素。
  • push_front<typelist, elem>:向开头插入一个元素。
  • push_back<typelist, elem>:向结尾插入一个元素。
  • replace_front<typelist, elem>:替换第一个元素。
  • is_empty<typelist>:判断是否为空。
  • find<typelist, index>:查找下标为index的元素。
  • get_maxsize_type<typelist>:容器中尺寸(sizeof)最大的元素。
  • reverse<typelist>:翻转容器中的元素。

3. 接口实现

3.1 容器

cpp 复制代码
template<typename... Elems>
struct typelist{};

3.2 front<typelist>

cpp 复制代码
template<typename TPLT>// typelist的简写
struct front;

struct front<typelist<FirstElem, OtherElems...>>
{
    using type = FirstElem;
};

3.3 size<typelist>

cpp 复制代码
template<typename TPLT>
struct size;

template<typename... Elems>
struct size<typelist<Elems...>>
{
    static inline const value = sizeof...(Elems);
};

3.4 pop_front<typelist, elem>

cpp 复制代码
template<typename TPLT>
struct pop_front;

template<typename FirstElem, typename... OtherElems>
struct pop_front<typelist<FirstElem, OtherElems...>
{
    using type = typelist<OtherrElems...>;
};

3.5 push_front<typelist, elem>

cpp 复制代码
template<typename TPLT, typename newElem>
struct push_front;

template<typename... Elems, typename newElem>
struct push_front<typelist<Elems...>, newElem>
{
    using type = typelist<newElem, Elems...>;
};

3.6 push_back<typelist, elem>

cpp 复制代码
template<typename TPLT, typename newElem>
struct push_back;

template<typename... Elems, typename newElem>
struct push_back<typelist<Elems...>, newElem>
{
    using type = typelist<Elems..., newElem>;
};

3.7 replace_front<TPLT, elem>

cpp 复制代码
template<typename TPLT, typename Elem>
struct replace_front;

template<typename FirstElem, typename... OtherElems, typename Elem>
struct replace_front<typelist<FirstElem, OtherElems...>, Elem>
{
    using type = typelist<Elem, OtherElems...>;
};

3.8 is_empty<TPLT>

cpp 复制代码
template<typename TPLT>
struct is_empty;

template<typename... Elems>
struct is_empty
{
    static inline const bool value = sizeof...(Elems) == 0;
};

3.9 find<typelist, index>

cpp 复制代码
template<typename TPLT, size_t index>
struct find : find<typename pop_front<TPLT>::type, index - 1>
{
	
};

template<typename TPLT>
struct find<TPLT, 0> :front<TPLT>
{
};

3.10 get_maxsize_type<typelist>

cpp 复制代码
template<typename TPLT>
struct get_maxsize_type
{
private:
	using FirstType = typename front<TPLT>::type;
	using RemainLT = typename pop_front<TPLT>::type;
	using RemainMaxType = typename get_maxsize_type<RemainLT>::type;
public:
	using type = conditional_t < (sizeof(FirstType) > sizeof(RemainMaxType)),
		FirstType, RemainMaxType >;
};

template<typename Elem>
struct get_maxsize_type<typelist<Elem>>
{
	using type = Elem;
};

template<>
struct get_maxsize_type<typelist<>>;

3.11 reverse<typelist>

cpp 复制代码
template<typename TPLT>
struct reverse
{
private:
	using FirstElem = typename front<TPLT>::type;
	using RemainTL = typename pop_front<TPLT>::type;
	using ReversedRemainTL = typename reverse<RemainTL>::type;
public:
	using type = typename push_back<ReversedRemainTL, FirstElem>::type;
};


template<>
struct reverse<typelist<>>
{
	using type = typelist<>;
};

cpp 复制代码
template<typename TPLT, bool = is_empty<TPLT>::value>
struct reverse;

template<typename TPLT>
struct reverse<TPLT, false>
{
private:
	using FirstElem = typename front<TPLT>::type;
	using RemainTL = typename pop_front<TPLT>::type;
	using ReversedRemainTL = typename reverse<RemainTL>::type;
public:
	using type = typename push_back<ReversedRemainTL, FirstElem>::type;
};

template<typename TPLT>
struct reverse<TPLT, true>
{
	using type = typelist<>;
};

4. 完整代码

cpp 复制代码
#include <iostream>
#include <string>
#include "boost/type_index.hpp"

using namespace std;

template<typename T>
class TypeGetter
{
public:
	static inline const std::string name = boost::typeindex::type_id_with_cvr<T>().pretty_name();
};


namespace myTypeList
{
	template<typename... T>
	struct typelist {};

	template<typename TPLT>
	struct front;

	template<typename FirstType, typename... Others>
	struct front < typelist<FirstType, Others...>>
	{
		using type = FirstType;
	};

	template<typename TPLT>
	struct size;

	template<typename... Args>
	struct size<typelist<Args...>>
	{
		static const inline size_t value = sizeof...(Args);
	};

	template<typename TPLT>
	struct is_empty;

	template<typename... Elems>
	struct is_empty<typelist<Elems...>>
	{
		static constexpr bool value = sizeof...(Elems) == 0;
	};


	template<typename TPLT>
	struct pop_front;

	
	template<typename FirstType, typename... Others>
	struct pop_front< typelist<FirstType, Others...> >
	{
		using type = typelist<Others...>;
	};

	template<typename TPLT, typename T>
	struct push_front;

	template<typename... Types, typename T>
	struct push_front<typelist<Types...>, T>
	{
		using type = typelist<T, Types...>;
	};

	template<typename TPLT, typename T>
	struct push_back;

	template<typename... Types, typename T>
	struct push_back<typelist<Types...>, T>
	{
		using type = typelist<Types..., T>;
	};

	template<typename TPLT, typename newElem>
	struct replace_front;

	template<typename FirstElem, typename... OtherElems, typename newElem>
	struct replace_front<typelist<FirstElem, OtherElems...>, newElem>
	{
		using type = typelist<newElem, OtherElems...>;
	};

	

	template<typename TPLT, size_t index>
	struct find : find<typename pop_front<TPLT>::type, index - 1>
	{
		
	};

	/*
		和下面的写法是等价的

	template<typename TPLT, size_t index>
	struct find
	{
		using type = typename find<typename pop_front<TPLT>::type, index - 1>::type;
	};

	*/

	template<typename TPLT>
	struct find<TPLT, 0> :front<TPLT>
	{
	};

	/*
		get_maxsize_type: 获取typelist中尺寸最大的类型
	*/

	template<typename TPLT>
	struct get_maxsize_type
	{
	private:
		using FirstType = typename front<TPLT>::type;
		using RemainLT = typename pop_front<TPLT>::type;
		using RemainMaxType = typename get_maxsize_type<RemainLT>::type;
	public:
		using type = conditional_t < (sizeof(FirstType) > sizeof(RemainMaxType)),
			FirstType, RemainMaxType >;
	};

	template<typename Elem>
	struct get_maxsize_type<typelist<Elem>>
	{
		using type = Elem;
	};

	template<>
	struct get_maxsize_type<typelist<>>;


	/*
		reverse: 翻转typelist
	*/
	/*
	
	// 版本一

	template<typename TPLT>
	struct reverse
	{
	private:
		using FirstElem = typename front<TPLT>::type;
		using RemainTL = typename pop_front<TPLT>::type;
		using ReversedRemainTL = typename reverse<RemainTL>::type;
	public:
		using type = typename push_back<ReversedRemainTL, FirstElem>::type;
	};


	template<>
	struct reverse<typelist<>>
	{
		using type = typelist<>;
	};
	*/

	template<typename TPLT, bool = is_empty<TPLT>::value>
	struct reverse;

	template<typename TPLT>
	struct reverse<TPLT, false>
	{
	private:
		using FirstElem = typename front<TPLT>::type;
		using RemainTL = typename pop_front<TPLT>::type;
		using ReversedRemainTL = typename reverse<RemainTL>::type;
	public:
		using type = typename push_back<ReversedRemainTL, FirstElem>::type;
	};

	template<typename TPLT>
	struct reverse<TPLT, true>
	{
		using type = typelist<>;
	};
}

class A {};

int main()
{
	using TPL_1 = myTypeList::typelist<char, short, int, A, double>;
	using TPL_2 = myTypeList::typelist<>;

	

	cout << "TPL_1 的第一个类型为" << TypeGetter< myTypeList::front<TPL_1>::type >::name << endl;
	//cout << "TPL_2 的第一个类型为" << TypeGetter< myTypeList::front<TPL_2>::type >::name << endl;

	cout << "TPL_1 的size为:" << myTypeList::size<TPL_1>::value << endl;
	cout << "TPL_2 的size为:" << myTypeList::size<TPL_2>::value << endl;

	cout << "TPL_1 的pop_front为:" << TypeGetter< myTypeList::pop_front< TPL_1 >::type >::name << endl;
	//cout << "TPL_2 的pop_front为:" << TypeGetter< myTypeList::pop_front< TPL_2 >::type >::name << endl;

	cout << "TPL_1 push_front bool 为:" << TypeGetter< myTypeList::push_front<TPL_1, bool>::type>::name << endl;
	cout << "TPL_2 push_front bool 为:" << TypeGetter< myTypeList::push_front<TPL_2, bool>::type>::name << endl;

	cout << "TPL_1 push_back bool 为:" << TypeGetter< myTypeList::push_back<TPL_1, bool>::type>::name << endl;
	cout << "TPL_2 push_back bool 为:" << TypeGetter< myTypeList::push_back<TPL_2, bool>::type>::name << endl;

	cout << "TPL_1 replace_front with char 为:" << TypeGetter < myTypeList::replace_front< TPL_1, char >::type>::name << endl;

	cout << "TPL_1 index 2 type 为:" << TypeGetter< myTypeList::find<TPL_1, 2>::type > ::name << endl;

	cout << "TPL_1 max size type 为:" << TypeGetter<myTypeList::get_maxsize_type<TPL_1>::type>::name << endl;

	cout << "TPL_1         为:" << TypeGetter<TPL_1>::name << endl;
	cout << "TPL_1 reverse 为:" << TypeGetter<myTypeList::reverse<TPL_1>::type>::name << endl;

	return 0;
}

运行结果如下:

相关推荐
琑951 小时前
Next.js项目MindAI教程 - 第四章:用户认证系统
开发语言·javascript·数据库·人工智能·mysql·typescript·node.js
已是上好佳4 小时前
Tcp网络通信的基本流程梳理
linux·运维·服务器·c++
WangMing_X4 小时前
C#实现动态验证码生成器:安全防护与实际应用场景
开发语言·安全·c#·验证码·图片
m0_555762904 小时前
qt designer中的Spacer相关设置
服务器·开发语言·qt
jk_1015 小时前
MATLAB中enumeration函数用法
开发语言·matlab
十年一梦实验室6 小时前
C++ 中的 RTTI(Run-Time Type Information,运行时类型识别)
开发语言·c++
纽约恋情6 小时前
C++——STL 常用的排序算法
开发语言·c++·排序算法
千里码aicood6 小时前
【2025】基于python+django的驾校招生培训管理系统(源码、万字文档、图文修改、调试答疑)
开发语言·python·django
小李苦学C++7 小时前
C++模板特化与偏特化
开发语言·c++
小王努力学编程7 小时前
元音辅音字符串计数leetcode3305,3306
开发语言·c++·学习·算法·leetcode