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

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.mzph.cn/news/895147.shtml

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

相关文章

springboot 事务管理

在Spring Boot中&#xff0c;事务管理是通过Spring框架的事务管理模块来实现的。Spring提供了声明式事务管理和编程式事务管理两种方式。通常&#xff0c;我们使用声明式事务管理&#xff0c;因为它更简洁且易于维护。 1. 声明式事务管理 声明式事务管理是通过注解来实现的。…

windows通过网络向Ubuntu发送文件/目录

由于最近要使用树莓派进行一些代码练习&#xff0c;但是好多东西都在windows里或虚拟机上&#xff0c;就想将文件传输到树莓派上&#xff0c;但试了发现u盘不能简单传送&#xff0c;就在网络上找到了通过windows 的scp命令传送 前提是树莓派先开启ssh服务&#xff0c;且Window…

字节跳动后端一面

&#x1f4cd;1. Gzip压缩技术详解 Gzip是一种流行的无损数据压缩格式&#xff0c;它使用DEFLATE算法来减少文件大小&#xff0c;广泛应用于网络传输和文件存储中以提高效率。 &#x1f680; 使用场景&#xff1a; • 网站优化&#xff1a;通过压缩HTML、CSS、JavaScript文件来…

Leetcode 3448. Count Substrings Divisible By Last Digit

Leetcode 3448. Count Substrings Divisible By Last Digit 1. 解题思路2. 代码实现 题目链接&#xff1a;3448. Count Substrings Divisible By Last Digit 1. 解题思路 这一题的话我们走的是一个累积数组的思路。 首先&#xff0c;我们使用一个cache数组记录下任意段数字…

三维模拟-机械臂自翻车

机械仿真 前言效果图后续 前言 最近在研究Unity机械仿真&#xff0c;用Unity实现其运动学仿真展示的功能&#xff0c;发现一个好用的插件“MGS-Machinery-master”&#xff0c;完美的解决了Unity关节定义缺少液压缸伸缩关节功能&#xff0c;内置了多个场景&#xff0c;讲真的&…

USB子系统学习(四)用户态下使用libusb读取鼠标数据

文章目录 1、声明2、HID协议2.1、描述符2.2、鼠标数据格式 3、应用程序4、编译应用程序5、测试6、其它 1、声明 本文是在学习韦东山《驱动大全》USB子系统时&#xff0c;为梳理知识点和自己回看而记录&#xff0c;全部内容高度复制粘贴。 韦老师的《驱动大全》&#xff1a;商…

2月9日QT

优化登录框&#xff1a; 当用户点击取消按钮&#xff0c;弹出问题对话框&#xff0c;询问是否要确定退出登录&#xff0c;并提供两个按钮&#xff0c;yes|No&#xff0c;如果用户点击的Yes&#xff0c;则关闭对话框&#xff0c;如果用户点击的No&#xff0c;则继续登录 当用户…

安卓路由与aop 以及 Router-api

安卓路由&#xff08;Android Router&#xff09;和AOP&#xff08;面向切面编程&#xff09;是两个在Android开发中常用的概念。下面我将详细讲解这两个概念及其在Android开发中的应用。 一、安卓路由 安卓路由主要用于在应用程序中管理不同组件之间的导航和通信。它可以简化…

大模型赋能网络安全整体应用流程概述

一、四个阶段概述 安全大模型的应用大致可以分为四个阶段: 阶段一主要基于开源基础模型训练安全垂直领域的模型; 阶段二主要基于阶段一训练出来的安全大模型开展推理优化、蒸馏等工序,从而打造出不同安全场景的专家模型,比如数据安全领域、安全运营领域、调用邮件识别领…

nexus部署及配置https访问

1. 使用docker-compose部署nexus docker-compose-nexus.yml version: "3" services:nexus:container_name: my-nexusimage: sonatype/nexus3:3.67.1hostname: my-nexusnetwork_mode: hostports:- 8081:8081deploy:resources:limits:cpus: 4memory: 8192Mreservations…

史上最快 Python版本 Python 3.13 安装教程

Python3.13安装和配置 一、Python的下载 1. 网盘下载地址 (下载速度比较快&#xff0c;推荐&#xff09; Python3.13.0下载&#xff1a;Python3.13.0下载地址&#xff08;windows&#xff09;3.13.0下载地址&#xff08;windows&#xff09; 点击下面的下载链接&#xff0c…

Docker从入门到精通- 容器化技术全解析

第一章&#xff1a;Docker 入门 一、什么是 Docker&#xff1f; Docker 就像一个超级厉害的 “打包神器”。它能帮咱们把应用程序和它运行所需要的东东都整整齐齐地打包到一起&#xff0c;形成一个独立的小盒子&#xff0c;这个小盒子在 Docker 里叫容器。以前呢&#xff0c;…

ProcessingP5js数据可视化

折线图绘制程序设计说明 可以读取表格数据&#xff0c;并转换成折线图&#xff0c;条形图和饼状图&#xff0c;并设计了衔接动画效果 1. 功能概述 本程序使用 Processing 读取 CSV 文件数据&#xff0c;并绘制带有坐标轴和数据点的折线图。横坐标&#xff08;X 轴&#xff09…

使用云计算,企业的数据监管合规问题如何解决?

使用云计算&#xff0c;企业的数据监管合规问题如何解决&#xff1f; 在当今这个信息化、数字化的时代&#xff0c;数据无疑成为了企业最宝贵的资产之一。随着云计算的普及&#xff0c;企业将大量数据存储在云端&#xff0c;不仅提升了效率&#xff0c;也带来了更多灵活性。然…

AWS Fargate

AWS Fargate 是一个由 Amazon Web Services (AWS) 提供的无服务器容器计算引擎。它使开发者能够运行容器化应用程序&#xff0c;而无需管理底层的服务器或虚拟机。简而言之&#xff0c;AWS Fargate 让你只需关注应用的容器本身&#xff0c;而不需要管理运行容器的基础设施&…

vue3+vite+eslint|prettier+elementplus+国际化+axios封装+pinia

文章目录 vue3 vite 创建项目如果创建项目选了 eslint prettier从零教你使用 eslint prettier第一步&#xff0c;下载eslint第二步&#xff0c;创建eslint配置文件&#xff0c;并下载好其他插件第三步&#xff1a;安装 prettier安装后配置 eslint (2025/2/7 补充) 第四步&am…

vLLM V1 重磅升级:核心架构全面革新

本文主要是 翻译简化个人评读&#xff0c;原文请参考&#xff1a;vLLM V1: A Major Upgrade to vLLM’s Core Architecture vLLM V1 开发背景 2025年1月27日&#xff0c;vLLM 开发团队推出 vLLM V1 alpha 版本&#xff0c;这是对框架核心架构的里程碑式升级。基于过去一年半的…

Jupyter Notebook自动保存失败等问题的解决

一、未生成配置文件 需要在命令行中&#xff0c;执行下面的命令自动生成配置文件 jupyter notebook --generate-config 执行后会在 C:\Users\用户名\.jupyter目录中生成文件 jupyter_notebook_config.py 二、在网页端打开Jupyter Notebook后文件保存失败&#xff1b;运行代码…

使用wpa_supplicant和wpa_cli 扫描wifi热点及配网

一&#xff1a;简要说明 交叉编译wpa_supplicant工具后会有wpa_supplicant和wpa_cli两个程序生产&#xff0c;如果知道需要连接的wifi热点及密码的话不需要遍历及查询所有wifi热点的名字及信号强度等信息的话&#xff0c;使用wpa_supplicant即可&#xff0c;否则还需要使用wpa_…

Flink (十七) :Table API SQL (五) 时区

Flink 为日期和时间提供了丰富的数据类型&#xff0c; 包括 DATE&#xff0c; TIME&#xff0c; TIMESTAMP&#xff0c; TIMESTAMP_LTZ&#xff0c; INTERVAL YEAR TO MONTH&#xff0c; INTERVAL DAY TO SECOND 。 Flink 支持在 session &#xff08;会话&#xff09;级别设置…