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

news2025/2/11 13:05:24

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

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 容器

template<typename... Elems>
struct typelist{};

3.2 front<typelist>

template<typename TPLT>// typelist的简写
struct front;

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

3.3 size<typelist>

template<typename TPLT>
struct size;

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

3.4 pop_front<typelist, elem>

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>

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>

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>

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>

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>

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>

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>

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<>;
};

4. 完整代码

 

#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;
}

 运行结果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2296329.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据可视化与交互融合:APP 界面设计的新维度

在数字化浪潮汹涌的当下&#xff0c;APP 已成为人们生活和工作中不可或缺的工具。如何在众多 APP 中脱颖而出&#xff0c;界面设计至关重要。而数据可视化与交互的融合&#xff0c;正为 APP 界面设计开辟了全新的维度。 数据可视化&#xff0c;简单来说&#xff0c;就是将复杂…

控制论与信息论:维纳和香农的核心分歧在于对「信息本质」的理解

控制论与信息论&#xff1a;维纳和香农的核心分歧在于对「信息本质」的理解 核心结论 控制论是「系统的方向盘」&#xff0c;通过反馈调节实现目标信息论是「信息的尺子」&#xff0c;量化信息传输的精度与效率根本分歧&#xff1a;维纳认为信息是「系统维持秩序的工具」&…

Baklib优化数字化内容管理用科技提升商业效率与增值潜力

内容概要 在当今数字化迅速发展的时代&#xff0c;数字化内容管理已成为企业提升竞争力的重要手段。Baklib作为一款强大的智能优化内容管理系统&#xff0c;通过先进的科技手段&#xff0c;帮助企业在内容管理和数据整合方面实现高效运作。Baklib 是什么类型的工具&#xff0c…

一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码及效果展示

一个基于ESP32S3和INMP441麦克风实现音频强度控制RGB灯带律动的代码示例&#xff0c;使用Arduino语言&#xff1a; 硬件连接 INMP441 VCC → ESP32的3.3VINMP441 GND → ESP32的GNDINMP441 SCK → ESP32的GPIO 17INMP441 WS → ESP32的GPIO 18INMP441 SD → ESP32的GPIO 16RG…

利用二分法进行 SQL 时间盲注

什么是时间盲注&#xff1f; SQL 盲注&#xff08;Blind SQL Injection&#xff09;是一种常见的 Web 安全漏洞&#xff0c;其中时间盲注是基于查询延迟的 SQL 注入方式。当服务器不返回可见的错误信息时&#xff0c;我们可以利用 SLEEP() 函数来判断查询结果是否符合预期。 …

基于STM32的声纹识别智能门锁

一、项目背景与意义 行业痛点&#xff1a;传统指纹锁存在表皮磨损识别失败风险&#xff0c;声纹具备活体检测特性 技术优势&#xff1a; - 采用MFCC&#xff08;梅尔频率倒谱系数&#xff09;替代传统FFT&#xff0c;提升说话人特征区分度 - 动态时间规整(DTW)算法解决语…

在CT107D单片机综合训练平台上实现外部中断控制LED闪烁

引言 在单片机开发中&#xff0c;外部中断是一个非常重要的功能&#xff0c;它可以让单片机在检测到外部信号变化时立即做出响应。本文将详细介绍如何在CT107D单片机综合训练平台上使用外部中断来控制LED灯的闪烁。我们将使用两种不同的方式来实现这一功能&#xff1a;一种是在…

C++ Primer 类型转换

欢迎阅读我的 【CPrimer】专栏 专栏简介&#xff1a;本专栏主要面向C初学者&#xff0c;解释C的一些基本概念和基础语言特性&#xff0c;涉及C标准库的用法&#xff0c;面向对象特性&#xff0c;泛型特性高级用法。通过使用标准库中定义的抽象设施&#xff0c;使你更加适应高级…

Visual Studio Code中文出现黄色框子的解决办法

Visual Studio Code中文出现黄色框子的解决办法 一、vsCode中文出现黄色框子-如图二、解决办法 一、vsCode中文出现黄色框子-如图 二、解决办法 点击 “文件”点击 “首选项”点击 “设置” 搜索框直接搜索unicode选择“文本编辑器”&#xff0c;往下滑动&#xff0c;找到“Un…

“可通过HTTP获取远端WWW服务信息”漏洞修复

环境说明&#xff1a;①操作系统&#xff1a;windows server&#xff1b;②nginx&#xff1a;1.27.1。 1.漏洞说明 “可通过HTTP获取远端WWW服务信息”。 修复前&#xff0c;在“响应标头”能看到Server信息&#xff0c;如下图所示&#xff1a; 修复后&#xff0c;“响应标头…

CAD 屏幕进度条

参考鸿视频实现&#xff0c;代码如下&#xff1a; 主类 using System.IO.Ports; using System.Threading; using System.Windows.Controls; using static IFoxDemo.进度条class; using static System.Windows.Forms.VisualStyles.VisualStyleElement.TrackBar;//[assembly: C…

小红书爬虫: 获取所需数据

小红书&#xff0c;又名 “小红书 ”或简称 “红”&#xff0c;已迅速成为中国社交和电子商务领域的重要参与者&#xff0c;成为一个不可或缺的平台。对于企业、营销人员和数据分析师来说&#xff0c;从小红书收集数据可以获得宝贵的洞察力&#xff0c;从而推动业务增长。虽然这…

使用sunshine和moonlight串流时的音频输出问题

设备&#xff1a;电脑和平板串流&#xff0c;把平板当副屏使用 1.如果启用安装steam音频驱动程序&#xff0c;则平板有声&#xff0c;电脑无声&#xff0c;在moonlight端可以设置平板和电脑同时发声&#xff0c;但是有点卡 2.只想电脑发声&#xff0c;平板无声 禁用安装steam…

活动预告 |【Part 2】Microsoft 安全在线技术公开课:通过扩展检测和响应抵御威胁

课程介绍 通过 Microsoft Learn 免费参加 Microsoft 安全在线技术公开课&#xff0c;掌握创造新机遇所需的技能&#xff0c;加快对 Microsoft Cloud 技术的了解。参加我们举办的“通过扩展检测和响应抵御威胁”技术公开课活动&#xff0c;了解如何更好地在 Microsoft 365 Defen…

网络工程师 (26)TCP/IP体系结构

一、层次 四层&#xff1a; 网络接口层&#xff1a;TCP/IP协议的最底层&#xff0c;负责网络层与硬件设备间的联系。该层协议非常多&#xff0c;包括逻辑链路和媒体访问控制&#xff0c;负责与物理传输的连接媒介打交道&#xff0c;主要功能是接收数据报&#xff0c;并把接收到…

GIS笔记之Shapefile与KML相互转换

在GIS应用中&#xff0c;各种不同类型数据的转换与使用是一个重要的环节。在这其中&#xff0c;Shapefile和KML是两种常见的数据形式&#xff0c;两者间的相互转换也是日常工作和学习绕不开的话题。在这里&#xff0c;我们将常用的几种数据转换方法整理如下。 1.Shapefile和KM…

【UVM】寄存器模型

寄存器模型的优势 sequence复用性高&#xff0c;方便对 DUT 中寄存器进行读写&#xff1b;提供了后门访问方式&#xff0c;可以不耗时的获取寄存器的值&#xff1b;可以很方便的对寄存器的 coverage 验证点的收集 寄存器模型基本概念 寄存器模型概念作用uvm_reg_field寄存器模…

WordPress博客在fnOS环境下的极简搭建与公网地址配置指南

文章目录 前言1. Docker下载源设置2. Docker下载WordPress3. Docker部署Mysql数据库4. WordPress 参数设置5. 飞牛云安装Cpolar工具6. 固定Cpolar公网地址7. 修改WordPress配置文件8. 公网域名访问WordPress 前言 你是否曾经为搭建自己的网站而头疼不已&#xff1f;是不是觉得…

计算机毕业设计SpringBoot校园二手交易小程序 校园二手交易平台(websocket消息推送+云存储+双端+数据统计)(源码+文档+运行视频+讲解视频)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

2025年前端面试题~ 【前端面试】更新

前言 金三银四的招聘季即将来临&#xff0c;对于怀揣前端梦想的求职者而言&#xff0c;这是机遇与挑战并存的黄金时段。前端面试可不只是简单的问答&#xff0c;它是一场对综合能力的深度检验。面试官会从多个维度考量&#xff0c;比如扎实的 HTML、CSS 和 JavaScript 基础&…