当前位置: 首页 > news >正文

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++ 模板元编程)

定义 类型列表&#xff0c;字面意思就是一个存储类型的列表&#xff0c;例如std::tuple<int, float, double, std::string>就是一个类型列表。 template<typename ...Ts> struct type_list {};基础操作 操作约束&#xff1a;对于所有操作&#xff0c;均要求参数…...

使用老北鼻CharGPT对话查询 Qt/C++ 使用gumbo-parse解析加载的html全过程

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

​ iOS App Store上传项目报错 缺少隐私政策网址(URL)解决方法

一、问题如下图所示&#xff1a; ​ 二、解决办法&#xff1a;使用Google浏览器&#xff08;翻译成中文&#xff09;直接打开该网址 https://www.freeprivacypolicy.com/free-privacy-policy-generator.php 按照要求填写APP信息&#xff0c;最后将生成的网址复制粘贴到隐私…...

设计模式第一课-单例模式(懒汉模式和饿汉模式)

单例模式 个人理解&#xff1a;单例模式实际就是通过类加载的方式获取到一个对象&#xff0c;并且保证这个对象在使用中只有一个&#xff0c;不允许再次被创建 一、懒汉模式 1、懒汉模式的基础写法 代码解释&#xff1a; &#xff08;1&#xff09;、编写LazySingleton类的…...

Yaml文件详解

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

【题解 线段树】[蓝桥杯 2022 省 A] 选数异或

题目描述&#xff1a; [蓝桥杯 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] 中选择两…...

宠物喂食器方案智能开发设计

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

chatgpt综述阅读理解

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

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&#xff08;大语言模型&#xff09;的爆火&#xff0c;不少企业都在寻找通过LLM解决企业业务问题的方法&#xff0c;以达到降本增效的效果。但是&#xff0c;当面对较为复杂的业务问题&#xff08;如&#xff1a;背景资料多、问题分类多、条件判断复杂、涉及模块多等&a…...

多级菜单 树结构 排序 前端 后端 java

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

LAN-Free在数据备份时的应用与优势

在灾备领域中&#xff0c;常见的备份架构有LAN、LAN-Free和Server-Free备份&#xff0c;其中LAN备份架构图见图1&#xff0c;LAN-Free备份架构图见图2&#xff0c;Server-Free备份架构图见图3&#xff0c;途中红色箭头为备份数据流量走向&#xff1a; 图 1 图 2 图 3 从图1、图…...

HTML 文档声明和语言设置

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

【C++基础知识学习笔记】精华版(复习专用)

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

探索ChatGPT在学术写作中的应用与心得

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

Android:怎么学习才能更好的进大厂呢?

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

CSS标点符号换行问题

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

jdbc Preparestatement防止SQL注入的原理

2023-10-28T03:37:11.264132Z 2 Execute select * from users where username liulemon and password \ or \1\ 1\ 可以看到这一行&#xff0c;预编译时&#xff1f;变成了转义字符 useServerPrepStmtstrue加上这句才能预编译...

如何控制 LLM 的输出格式和解析其输出结果?

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

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

12.找到字符串中所有字母异位词

&#x1f9e0; 题目解析 题目描述&#xff1a; 给定两个字符串 s 和 p&#xff0c;找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义&#xff1a; 若两个字符串包含的字符种类和出现次数完全相同&#xff0c;顺序无所谓&#xff0c;则互为…...

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要

根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分&#xff1a; 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...

Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案

在大数据时代&#xff0c;海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构&#xff0c;在处理大规模数据抓取任务时展现出强大的能力。然而&#xff0c;随着业务规模的不断扩大和数据抓取需求的日益复杂&#xff0c;传统…...

WPF八大法则:告别模态窗口卡顿

⚙️ 核心问题&#xff1a;阻塞式模态窗口的缺陷 原始代码中ShowDialog()会阻塞UI线程&#xff0c;导致后续逻辑无法执行&#xff1a; var result modalWindow.ShowDialog(); // 线程阻塞 ProcessResult(result); // 必须等待窗口关闭根本问题&#xff1a…...

基于鸿蒙(HarmonyOS5)的打车小程序

1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...