Type List(C++ 模板元编程)
定义
类型列表,字面意思就是一个存储类型的列表,例如std::tuple<int, float, double, std::string>
就是一个类型列表。
template<typename ...Ts> struct type_list {};
基础操作
操作约束:对于所有操作,均要求参数合法,即要求type_list
中至少有一个类型,或者提供的下标不越界。
-
is_empty
-
front
-
pop_front
-
push_front
-
push_back
-
back
-
pop_back
-
reverse
-
largest(支持自定义compare)
-
merge
-
insert
is_empty
template<typename Ts>
struct is_empty_impl : std::integral_constant<bool, false> {};template<>
struct is_empty_impl<type_list<>> : std::integral_constant<bool, true> {};template<typename Ts>
constexpr static bool is_empty = is_empty_impl<Ts>::value;
Front
template<typename T> struct front_impl {};template<typename T, typename ...Ts>
struct front_impl<type_list<T, Ts...>> {using type = T;
};template<typename T> using front = front_impl<T>::type;
Pop front
template<typename T> struct pop_front_impl {};template<typename T, typename ...Ts>
struct pop_front_impl<type_list<T, Ts...>> {using type = type_list<Ts...>;
};template<typename T> using pop_front = pop_front_impl<T>::type;
Push front
template<typename Tl, typename T> struct push_front_impl {};template<typename ...Ts, typename T>
struct push_front_impl<type_list<Ts...>, T> {using type = type_list<T, Ts...>;
};template<typename Tl, typename T>
using push_front = push_front_impl<Tl, T>::type;
Push back
template<typename Tl, typename T> struct push_back_impl {};template<typename ...Ts, typename T>
struct push_back_impl<type_list<Ts...>, T> {using type = type_list<Ts..., T>;
};template<typename Tl, typename T>
using push_back = push_back_impl<Tl, T>::type;
Back
template<typename Tl> struct back_impl {};template<typename T, typename ...Ts>
struct back_impl<type_list<T, Ts...>> : back_impl<type_list<Ts...>> {};template<typename T>
struct back_impl<type_list<T>> { using type = T; };template<typename Tl> using back = back_impl<Tl>::type;
Pop back
template<typename Tl> struct pop_back_impl {};template<typename T, typename ...Ts>
struct pop_back_impl<type_list<T, Ts...>>: push_front_impl<typename pop_back_impl<type_list<Ts...>>::type, T> {};template<typename T>
struct pop_back_impl<type_list<T>> { using type = type_list<>; };template<typename Tl> using pop_back = pop_back_impl<Tl>::type;
Reverse
template<typename Tl, bool empty = is_empty<Tl>> struct reverse_impl {};template<typename Tl>
struct reverse_impl<Tl, false>: push_back_impl<typename reverse_impl<pop_front<Tl>>::type, front<Tl>> {};template<typename Tl>
struct reverse_impl<Tl, true> { using type = type_list<>; };template<typename Tl>
using reverse = reverse_impl<Tl>::type;
Largest (可接收自定义类型比较函数:参考compare实现)
template<bool judge, typename T1, typename T2>
struct type_choose {using type = T2;
};template<typename T1, typename T2>
struct type_choose<true, T1, T2> {using type = T1;
};template<typename T1, typename T2>
struct compare : std::integral_constant<bool, false> {};template<typename T1, typename T2>
requires (sizeof(T1) > sizeof(T2))
struct compare<T1, T2> : std::integral_constant<bool, true> {};template<typename Tl, template<typename ...> typename C> struct largest_impl {};template<typename T, template<typename ...> typename C>
struct largest_impl<type_list<T>, C> {using type = T;
};template<typename T, typename ...Ts, template<typename ...> typename C>
struct largest_impl<type_list<T, Ts...>, C>: type_choose<C<T, typename largest_impl<type_list<Ts...>, C>::type>::value,T, typename largest_impl<type_list<Ts...>, C>::type> {};template<typename Tl, template<typename ...> typename C>
using largest = largest_impl<Tl, C>::type;
merge
template<typename Tl1, typename Tl2> struct merge_impl {};template<typename ...Ts1, typename ...Ts2>
struct merge_impl<type_list<Ts1...>, type_list<Ts2...>> {using type = type_list<Ts1..., Ts2...>;
};template<typename Tl1, typename Tl2>
using merge = merge_impl<Tl1, Tl2>::type;
insert
两个子模板会在insert_impl<type_list<Ts...>, 0, T>
sizeof...(Ts) > 0
的时候冲突,所以加上一个requires
约束一下。
template<typename Tl, int index, typename T> struct insert_impl {};template<typename Tf, typename ...Ts, int index, typename T>
requires (index > 0)
struct insert_impl<type_list<Tf, Ts...>, index, T>: push_front_impl<typename insert_impl<type_list<Ts...>, index - 1, T>::type, Tf> {};template<typename ...Ts, typename T>
struct insert_impl<type_list<Ts...>, 0, T>: push_front_impl<type_list<Ts...>, T> {};template<typename Tl, int index, typename T>
using insert = insert_impl<Tl, index, T>::type;
TEST
符合TDD,简单测试一下:
int main() {// is empty: 1 0 0std::cout << "is empty: ";std::cout << is_empty<type_list<>> << " "<< is_empty<type_list<int>> << " "<< is_empty<type_list<int, float, double>> << "\n\n";// front: 1 0std::cout << "front: ";std::cout << std::is_same_v<int, front<type_list<int, float>>> << " "<< std::is_same_v<float, front<type_list<int, float>>> << "\n\n";// pop front: 1 0 1std::cout << "pop front: ";std::cout << std::is_same_v<type_list<>, pop_front<type_list<int>>> << " "<< std::is_same_v<type_list<int>, pop_front<type_list<int>>> << " "<< std::is_same_v<type_list<int>, pop_front<type_list<float, int>>> << "\n\n";// push front: 1 0 1std::cout << "push front: ";std::cout << std::is_same_v<type_list<int>, push_front<type_list<>, int>> << " "<< std::is_same_v<type_list<int, float>, push_front<type_list<int>, float>> << " "<< std::is_same_v<type_list<float, int>, push_front<type_list<int>, float>> << "\n\n";// push back: 1 1 0std::cout << "push back: ";std::cout << std::is_same_v<type_list<int>, push_back<type_list<>, int>> << " "<< std::is_same_v<type_list<int, float>, push_back<type_list<int>, float>> << " "<< std::is_same_v<type_list<float, int>, push_back<type_list<int>, float>> << "\n\n";// back: 1 0 1std::cout << "back: ";std::cout << std::is_same_v<int, back<type_list<int>>> << " "<< std::is_same_v<int, back<type_list<int, float>>> << " "<< std::is_same_v<float, back<type_list<int, float>>> << "\n\n";// pop back: 1 1 0std::cout << "pop back: ";std::cout << std::is_same_v<type_list<>, pop_back<type_list<int>>> << " "<< std::is_same_v<type_list<float>, pop_back<type_list<float, int>>> << " "<< std::is_same_v<type_list<int>, pop_back<type_list<float, int>>> << "\n\n";// reverse: 1 0 1 1std::cout << "reverse: ";std::cout << std::is_same_v<type_list<>, reverse<type_list<>>> << " "<< std::is_same_v<type_list<int, float>, reverse<type_list<int, float>>> << " "<< std::is_same_v<type_list<float, int>, reverse<type_list<int, float>>> << " "<< std::is_same_v<type_list<int, float, double>, reverse<type_list<double, float, int>>> << "\n\n";// largest: 1, 0, 1// char, short, int32_t, int64_t, doublestd::cout << sizeof(char) << " " << sizeof(short) << " " << sizeof(int32_t)<< " " << sizeof(int64_t) << " " << sizeof(double) << "\n";using type1 = type_list<char, short, int32_t, int64_t, double>;using type2 = type_list<char, short, int32_t, double, int64_t>;std::cout << "largest: ";std::cout << std::is_same_v<double, largest<type1, compare>> << " "<< std::is_same_v<double, largest<type2, compare>> << " "<< std::is_same_v<int64_t, largest<type2, compare>> << "\n\n";// merge: 1 1 1 0std::cout << "merge: ";std::cout << std::is_same_v<type_list<int>, merge<type_list<>, type_list<int>>> << " "<< std::is_same_v<type_list<int>, merge<type_list<int>, type_list<>>> << " "<< std::is_same_v<type_list<int, float>, merge<type_list<int>, type_list<float>>> << " "<< std::is_same_v<type_list<int, float>, merge<type_list<float>, type_list<int>>> << "\n\n";// insert: 1 1 1std::cout << "insert: ";std::cout << std::is_same_v<type_list<int>, insert<type_list<>, 0, int>> << " "<< std::is_same_v<type_list<int, float, double>, insert<type_list<int, double>, 1, float>> << " "<< std::is_same_v<type_list<int, float, double>, insert<type_list<int, float>, 2, double>> << "\n";return 0;
}
Algorithm
Insert sort
维护尾部的有序性,每次加入一个新值,同时保证尾部的有效性,那么先实现一个insert_in_sorted<type_list<Ts...>, T>
- 找到第一个满足
C
的位置,并且在这个值前面插入
template<typename Tl, typename T, template<typename ...> typename C,bool empty = is_empty<Tl>>
struct insert_in_sorted_impl {};template<typename ...Ts, typename T, template<typename ...> typename C>
struct insert_in_sorted_impl<type_list<Ts...>, T, C, false>: type_choose<(C<front<type_list<Ts...>>, T>::value),push_front<type_list<Ts...>, T>,push_front<typename insert_in_sorted_impl<pop_front<type_list<Ts...>>, T, C>::type,front<type_list<Ts...>>>> {};template<typename ...Ts, typename T, template<typename ...> typename C>
struct insert_in_sorted_impl<type_list<Ts...>, T, C, true> {using type = type_list<T>;
};template<typename Tl, typename T, template<typename ...> typename C>
using insert_in_sorted = insert_in_sorted_impl<Tl, T, C>::type;
- 排序实现
template<typename Tl, template<typename ...> typename C,bool empty = is_empty<Tl>> struct insert_sort_impl {};template<typename ...Ts, template<typename ...> typename C>
struct insert_sort_impl<type_list<Ts...>, C, true> {using type = type_list<>;
};template<typename ...Ts, template<typename ...> typename C>
struct insert_sort_impl<type_list<Ts...>, C, false>: insert_in_sorted_impl<typename insert_sort_impl<pop_front<type_list<Ts...>>, C>::type,front<type_list<Ts...>>, C> {};template<typename Tl, template<typename ...> typename C>
using insert_sort = insert_sort_impl<Tl, C>::type;
- 测试一下结果对不对
int main() {// insert in sorted: 1 1 1 1 1std::cout << "insert in sorted: ";std::cout << std::is_same_v<type_list<int32_t>, insert_in_sorted<type_list<>, int32_t , compare>> << " "<< std::is_same_v<type_list<char, short, int32_t, int64_t>, insert_in_sorted<type_list<char, short, int32_t>, int64_t, compare>> << " "<< std::is_same_v<type_list<char, short, int32_t, int64_t>, insert_in_sorted<type_list<char, short, int64_t>, int32_t, compare>> << " "<< std::is_same_v<type_list<char, short, int32_t, float, int64_t>, insert_in_sorted<type_list<char, short, int32_t, int64_t>, float, compare>> << " "<< std::is_same_v<type_list<char, int32_t, long long, float, int64_t>, insert_in_sorted<type_list<char, long long, float, int64_t>, int32_t, compare>> << "\n";// insert sort: 1 1 1 1std::cout << "insert sort: ";std::cout << std::is_same_v<type_list<>, insert_sort<type_list<>, compare>> << " "<< std::is_same_v<type_list<char>, insert_sort<type_list<char>, compare>> << " "<< std::is_same_v<type_list<float, int>, insert_sort<type_list<int, float>, compare>> << " ";// 非稳定排序,相同大小的类型,初始在前面的会跑到后面去using type_list_sort = type_list<short int, char, short, int, long long, unsigned int, unsigned, unsigned long long, unsigned char>;using type_list_sort_ans = type_list<unsigned char, char, short, short int, unsigned, unsigned int, int, unsigned long long, long long>;std::cout << std::is_same_v<type_list_sort_ans, insert_sort<type_list_sort, compare>> << "\n";return 0;
}
相关文章:

Type List(C++ 模板元编程)
定义 类型列表,字面意思就是一个存储类型的列表,例如std::tuple<int, float, double, std::string>就是一个类型列表。 template<typename ...Ts> struct type_list {};基础操作 操作约束:对于所有操作,均要求参数…...

使用老北鼻CharGPT对话查询 Qt/C++ 使用gumbo-parse解析加载的html全过程
记下使用老北鼻CharGPT对话查询 Qt/C解析html网页全过程。 [gumbo-parse] Gumbo是HTML5解析算法作为纯C99库实现,没有外部依赖性。它被设计为其他工具和库的构建模块,比如linters、验证器、模板语言、重构和分析工具。详细说明参考original-README.md 目…...

iOS App Store上传项目报错 缺少隐私政策网址(URL)解决方法
一、问题如下图所示: 二、解决办法:使用Google浏览器(翻译成中文)直接打开该网址 https://www.freeprivacypolicy.com/free-privacy-policy-generator.php 按照要求填写APP信息,最后将生成的网址复制粘贴到隐私…...

设计模式第一课-单例模式(懒汉模式和饿汉模式)
单例模式 个人理解:单例模式实际就是通过类加载的方式获取到一个对象,并且保证这个对象在使用中只有一个,不允许再次被创建 一、懒汉模式 1、懒汉模式的基础写法 代码解释: (1)、编写LazySingleton类的…...

Yaml文件详解
目录 1、Yaml文件详解 2、详解k8s中的port 3、Service yaml 4、Deployment yaml文件详解 5、Pod yaml文件详解 1、Yaml文件详解 Kubernetes 支持 YAML 和 JSON 格式管理资源对象 JSON 格式:主要用于 api 接口之间消息的传递 YAML 格式:用于配置和管…...

【题解 线段树】[蓝桥杯 2022 省 A] 选数异或
题目描述: [蓝桥杯 2022 省 A] 选数异或 题目描述 给定一个长度为 n n n 的数列 A 1 , A 2 , ⋯ , A n A_{1}, A_{2}, \cdots, A_{n} A1,A2,⋯,An 和一个非负整数 x x x, 给定 m m m 次查询, 每次询问能否从某个区间 [ l , r ] [l, r] [l,r] 中选择两…...

宠物喂食器方案智能开发设计
现在年轻人特别是在一、二、三线城市的,工作节奏快、加班、出差、旅游成常态,无法经常在宠物身边照看,宠物智能自动喂食机能够解放宠主的双手和解决不能长时间在处的无奈,很好地满足了年轻宠物主照顾宠物的需求。宠物主和宠物都需…...

chatgpt综述阅读理解
Summary of ChatGPT-Related research and perspective towards the future of large language models 摘要 本文总结了语言模型在遵循指令和人类反馈方面的相关工作,包括训练语言模型来理解指令并按照指令执行任务,以及提高语言模型的性能和理解能力的…...

XCTF-RSA-2:baigeiRSA2、 cr4-poor-rsa
baigeiRSA2 题目描述 import libnum from Crypto.Util import number from functools import reduce from secret import flagn 5 size 64 while True:ps [number.getPrime(size) for _ in range(n)]if len(set(ps)) n:breake 65537 n reduce(lambda x, y: x*y, ps) m …...

js 根据word文档模板导出内容
一、创建word导出模板 1、本地创建一个test.docx 2、将最终需要的文档内容及样式编辑完成(图1) 3、将所需动态值的位置,替换为变量参数(图2) 注: 动态值书写 图1 图2 模板值的书写要求 二、项目中使用 1、安装依赖 npm install docxtemplater-image-module-free --save n…...

AIGC | 如何用“Flow”,轻松解决复杂业务问题
随着LLM(大语言模型)的爆火,不少企业都在寻找通过LLM解决企业业务问题的方法,以达到降本增效的效果。但是,当面对较为复杂的业务问题(如:背景资料多、问题分类多、条件判断复杂、涉及模块多等&a…...

多级菜单 树结构 排序 前端 后端 java
目录 省流: 正文: v1.0版 前端传的值: 后端代码: v2.0版 v3.0版 省流: 前端提交过来整个树即可。 给整个树进行sort。代码如下: public static void sort(List<Node> tree){int i 0;for…...

LAN-Free在数据备份时的应用与优势
在灾备领域中,常见的备份架构有LAN、LAN-Free和Server-Free备份,其中LAN备份架构图见图1,LAN-Free备份架构图见图2,Server-Free备份架构图见图3,途中红色箭头为备份数据流量走向: 图 1 图 2 图 3 从图1、图…...

HTML 文档声明和语言设置
HTML 文档声明 DOCTYPE 文档类型声明,用于告诉浏览器的解析器,该以那种 HTML 版本来解析这个文件。 HTML 5 版本声明 <!DOCTYPE html>XHTML 1.0 严格版声明 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http:/…...

【C++基础知识学习笔记】精华版(复习专用)
常用语法 函数重载(Overload) 规则: 函数名相同 参数个数不同、参数类型不同、参数顺序不同 注意: 返回值类型与函数重载无关 调用函数时,实参的隐式类型转换可能会产生二义性 默认参数 C++ 允许函数设置默认参数,在调用时可以根据情况省略实参。规则如下: 默认参数只能…...

探索ChatGPT在学术写作中的应用与心得
随着人工智能的迅猛发展,ChatGPT作为一种强大的自然语言处理模型,逐渐在学术界引起了广泛的关注。本文将探讨ChatGPT在学术写作中的应用,并分享使用ChatGPT进行学术写作时的一些经验和心得。 01 — ChatGPT在学术写作中的应用 1.文献综述和…...

Android:怎么学习才能更好的进大厂呢?
怎么学习才能更好的进大厂呢? 很多朋友都在问这个问题。 其实没有什么特别的技巧,就是依靠自己的毅力和决心。一天做不到,就一个月;一个月做不到,就一年。只要有决心,无论学历或资历如何,都不是…...

CSS标点符号换行问题
最近遇到一个奇怪的现象,元素中中文文本正常显示,但是加了一堆符号后中文文本居然换行了. div{width: 200px;border: 1px solid blue;word-break: break-all;} <div>文本</div>经过研究发现,因为标点符号不允许出现在行首和行尾,连带着符号…...

jdbc Preparestatement防止SQL注入的原理
2023-10-28T03:37:11.264132Z 2 Execute select * from users where username liulemon and password \ or \1\ 1\ 可以看到这一行,预编译时?变成了转义字符 useServerPrepStmtstrue加上这句才能预编译...

如何控制 LLM 的输出格式和解析其输出结果?
现在很多人对于如何使用像 ChatGPT 这样的 LLM 已经比较有经验了,可以使用各种不同的 Prompt 得到自己想要的结果。但有时候我们的使用场景不局限于手动操作,而是需要结合程序去调用 API,并且解析 API 的返回结果,从而实现一些自动…...

【Linux】 ps 命令使用
ps (英文全拼:process status)命令用于显示当前进程的状态,类似于 windows 的任务管理器。 语法 ps [选项] ps命令 -Linux手册页 著者 ps最初由布兰科兰克斯特撰写<lankestefwi.uva.nl>。迈克尔K约翰逊<johnsonmred…...

C++二分查找算法的应用:长度递增组的最大数目
本文涉及的基础知识点 二分查找 题目 给你一个下标从 0 开始、长度为 n 的数组 usageLimits 。 你的任务是使用从 0 到 n - 1 的数字创建若干组,并确保每个数字 i 在 所有组 中使用的次数总共不超过 usageLimits[i] 次。此外,还必须满足以下条件&…...

提示3D标题编辑器仍在运行怎么解决,以及3D标题编辑器怎么使用
在进行视频剪辑时,尤其是剪辑一些带有文字的开场视频,一般都会使用具有立体效果的3D标题,这样制作出来的视频效果不仅好看,还非常的炫酷,但是对于一些刚刚开始接触视频剪辑的小伙伴来说,可能对3D标题还不是…...

1. PPT高效初始化设置
1. PPT高效初始化设置 软件安装:Office 2019 主题和颜色 颜色可以在白天与黑夜切换,护眼 切换成了黑色 撤回次数 撤回次数太少,只有20次怎么办 自动保存 有时忘记保存就突然关闭,很需要一个自动保存功能 图片压缩 图…...

el-cascader级联选择器选中一个全选中问题
问题 只选中一个却把同级全选中 解决 :props中添加label、value、children属性 label、value、children属性值需要和后端返回的集合中的字段名保持一致 后端返回数据:...

Opencascad(C++)-创建自定义坐标系
文章目录 1、前言2、在Opencascad中显示小的坐标系3、在Opencascad中创建自定义的坐标系 1、前言 在Opencascad开发时,在view中可以显示小的坐标系,但是有时我们需要在建模时创建基准坐标系,当然可以作为工件坐标系也可以作为基准坐标系。本…...

MySQL数据库入门到大牛_01_数据库概述
文章目录 1. 为什么要使用数据库2. 数据库与数据库管理系统2.1 数据库的相关概念2.2 数据库与数据库管理系统的关系2.3 常见的数据库管理系统排名(DBMS)2.4 常见的数据库介绍 3. MySQL介绍3.1 概述3.2 MySQL发展史重大事件3.3 关于MySQL 8.03.4 Why choose MySQL?3.5 Oracle v…...

Web - Servlet详解
目录 前言 一 . Servlet简介 1.1 动态资源和静态资源 1.2 Servlet简介 二 . Servlet开发流程 2.1 目标 2.2 开发过程 三 . Servlet注解方式配置 编辑 四 . servlet生命周期 4.1 生命周期简介 4.2 生命周期测试 4.3 生命周期总结 五 . servlet继承结构 5.1 ser…...

postgresql 触发器如何生成递增序列号,从1开始,并且每天重置
大家好,我是三叔,许久不见,这期给大家介绍一下笔者在开发中遇到的业务处理:pgsql 创建触发器生成每日递增序列,并且第二天重置,根据不同的用户进行不同的控制。 1.创建生成递增序列的 table 表 -- 创建us…...

“第五十九天”
这是昨天那道题,这个后面自己的处理思路还是差了点,这道题关键感觉就是对进位的处理的,由于进位的存在,所以处理数据的时候只能从最低位开始,我一开始是从高位处理的,而且后面越来越迷,这个点一…...