tuple 简易实现(C++ 模板元编程)
std::tuple
在标准库里面,tuple主要有下面四个类模板 or 函数模板
tupletuple_sizetuple_elementget
在后续有实现:tuple_size_v = tuple_size::value和tuple_element_t = tuple_element::type。
事例Example:
auto tup = std::tuple<int, float, double, std::string>(0, 1.0, 2.0, "aaa");
std::cout << std::get<0>(tup) << " " << std::get<1>(tup)<< " " << std::get<2>(tup) << " " << std::get<3>(tup) << "\n";std::cout << std::tuple_size<decltype(tup)>::value << "\n";
std::cout << std::tuple_size_v<decltype(tup)> << "\n";std::tuple_element<3, decltype(tup)>::type a = "aaa";
std::cout << a << "\n";
std::tuple_element_t<3, decltype(tup)> b = "aaa";
std::cout << b << "\n";
sample:tuple
tuple
仿造stl:tuple的实现,采用模板递归继承的方式:
template<typename ...Ts> struct tuple;template<typename T> struct tuple<T> {using type = tuple;using value_type = T;T value_;
};template<typename T, typename ...Ts> struct tuple<T, Ts...> {using type = tuple;using value_type = T;using super_type = tuple<Ts...>;T value_;super_type rest_;
};
添加构造函数
template<typename Tv>
requires std::is_same_v<std::decay_t<Tv>, T>
tuple(Tv&& value) : value_(std::forward<Tv>(value)) {}
template<typename Tv, typename ...Tvs>
requires std::is_same_v<std::decay_t<Tv>, T>
tuple(Tv&& value, Tvs&& ...rest): value_(std::forward<Tv>(value)),rest_(super_type(std::forward<Tvs>(rest)...)) {}
test:
const std::string str1 = "lifehappy";
tuple<int, float, double, std::string> a1(114514, 114.514f, 114.514, std::move(str1));
std::cout << a1.value_ << " " << a1.rest_.value_ << " " << a1.rest_.rest_.value_ << " " << a1.rest_.rest_.rest_.value_ << "\n";
std::cout << str1 << " str1\n";std::string str2 = "lifehappy";
tuple<int, float, double, std::string> a2(114514, 114.514f, 114.514, std::move(str2));
std::cout << a2.value_ << " " << a2.rest_.value_ << " " << a2.rest_.rest_.value_ << " " << a2.rest_.rest_.rest_.value_ << "\n";
std::cout << str2 << " str2\n";
114514 114.514 114.514 lifehappy
lifehappy str1
114514 114.514 114.514 lifehappy
str2
为了让大家方便访问tuple里的内容,并没有采用继承的方式实现,但是,在后续的类模板中,均套用一下tuple类模板:
template<typename ...Ts> struct tuple;template<typename T> struct tuple<T> {using type = tuple;using value_type = T;T value_;template<typename Tv>requires std::is_same_v<std::decay_t<Tv>, T>tuple(Tv&& value) : value_(std::forward<Tv>(value)) {}tuple() {}~ tuple() {}
};template<typename T, typename ...Ts> struct tuple<T, Ts...> : tuple<Ts...> {using type = tuple;using value_type = T;using super_type = tuple<Ts...>;T value_;template<typename Tv, typename ...Tvs>requires std::is_same_v<std::decay_t<Tv>, T>tuple(Tv&& value, Tvs&& ...rest): value_(std::forward<Tv>(value)),super_type(std::forward<Tvs>(rest)...) {}tuple() {}~ tuple() {}
};
tuple_size
template<typename T> struct tuple_size {};template<typename ...Ts>
struct tuple_size<tuple<Ts...>> : std::integral_constant<int, sizeof...(Ts)> {};template<typename T>
constexpr static int tuple_size_v = tuple_size<T>::value;
tuple_element
template<int N, typename T> struct tuple_element {};template<int N, typename ...Ts>
struct tuple_element<N, tuple<Ts...>> : tuple_element<N - 1, typename tuple<Ts...>::super_type> {};template<typename ...Ts>
struct tuple_element<0, tuple<Ts...>> { using type = tuple<Ts...>::value_type; };template<int N, typename T>
using tuple_element_t = tuple_element<N, T>::type;
get
由于继承,所以可以通过static_cast<T>(tuple),T必须是满足条件的某个基类,那么先要实现一个获得第几代父亲类型的类模板:
template<int N, typename T> struct tuple_type_impl {};template<int N, typename ...Ts>
struct tuple_type_impl<N, tuple<Ts...>>: tuple_type_impl<N - 1, typename tuple<Ts...>::super_type> {};template<typename ...Ts>
struct tuple_type_impl<0, tuple<Ts...>> {using type = tuple<Ts...>::type;
};template<int N, typename T>
using tuple_type = tuple_type_impl<N, T>::type;
接着就可以通过static_cast得到其对应的类型value了:
template<int N, typename ...Ts>
auto&& get(tuple<Ts...> &tup) {using type = tuple_type<N, tuple<Ts...>>;return static_cast<type&>(tup).value_;
}
完整代码
#include <iostream>
#include <type_traits>template<typename ...Ts> struct tuple;template<typename T> struct tuple<T> {using type = tuple;using value_type = T;T value_;template<typename Tv>requires std::is_same_v<std::decay_t<Tv>, T>tuple(Tv&& value) : value_(std::forward<Tv>(value)) {}tuple() {}~ tuple() {}
};template<typename T, typename ...Ts> struct tuple<T, Ts...> : tuple<Ts...> {using type = tuple;using value_type = T;using super_type = tuple<Ts...>;T value_;template<typename Tv, typename ...Tvs>requires std::is_same_v<std::decay_t<Tv>, T>tuple(Tv&& value, Tvs&& ...rest): value_(std::forward<Tv>(value)),super_type(std::forward<Tvs>(rest)...) {}tuple() {}~ tuple() {}
};template<typename T> struct tuple_size {};template<typename ...Ts>
struct tuple_size<tuple<Ts...>> : std::integral_constant<int, sizeof...(Ts)> {};template<typename T>
constexpr static int tuple_size_v = tuple_size<T>::value;template<int N, typename T> struct tuple_element {};template<int N, typename ...Ts>
struct tuple_element<N, tuple<Ts...>> : tuple_element<N - 1, typename tuple<Ts...>::super_type> {};template<typename ...Ts>
struct tuple_element<0, tuple<Ts...>> { using type = tuple<Ts...>::value_type; };template<int N, typename T>
using tuple_element_t = tuple_element<N, T>::type;template<int N, typename T> struct tuple_type_impl {};template<int N, typename ...Ts>
struct tuple_type_impl<N, tuple<Ts...>>: tuple_type_impl<N - 1, typename tuple<Ts...>::super_type> {};template<typename ...Ts>
struct tuple_type_impl<0, tuple<Ts...>> {using type = tuple<Ts...>::type;
};template<int N, typename T>
using tuple_type = tuple_type_impl<N, T>::type;template<int N, typename ...Ts>
auto&& get(tuple<Ts...> &tup) {using type = tuple_type<N, tuple<Ts...>>;return static_cast<type&>(tup).value_;
}int main() {const std::string str1 = "lifehappy";tuple<int, float, double, std::string> a1(114514, 114.514f, 114.514, std::move(str1));// std::cout << a1.value_ << " " << a1.rest_.value_ << " " << a1.rest_.rest_.value_ << " " << a1.rest_.rest_.rest_.value_ << "\n";// std::cout << str1 << " str1\n";std::string str2 = "lifehappy";tuple<int, float, double, std::string> a2(114514, 114.514f, 114.514, std::move(str2));// std::cout << a2.value_ << " " << a2.rest_.value_ << " " << a2.rest_.rest_.value_ << " " << a2.rest_.rest_.rest_.value_ << "\n";// std::cout << str2 << " str2\n";std::cout << tuple_size_v<decltype(a1)> << " " << tuple_size<decltype(a2)>::value << "\n";std::cout << std::is_same_v<tuple_element<0, decltype(a1)>::type, tuple_element_t<0, decltype(a1)>> << " "<< std::is_same_v<tuple_element<1, decltype(a1)>::type, tuple_element_t<1, decltype(a1)>> << " "<< std::is_same_v<tuple_element<2, decltype(a1)>::type, tuple_element_t<2, decltype(a1)>> << " "<< std::is_same_v<tuple_element<3, decltype(a1)>::type, tuple_element_t<3, decltype(a1)>> << "\n";std::cout << get<0>(a1) << " " << get<1>(a1) << " "<< get<2>(a1) << " " << get<3>(a1) << "\n";get<0>(a2) = 415411;std::cout << get<0>(a2) << " " << get<1>(a2) << " "<< get<2>(a2) << " " << get<3>(a2) << "\n";return 0;
}
4 4
1 1 1 1
114514 114.514 114.514 lifehappy
415411 114.514 114.514 lifehappy
相关文章:
tuple 简易实现(C++ 模板元编程)
std::tuple 在标准库里面,tuple主要有下面四个类模板 or 函数模板 tupletuple_sizetuple_elementget 在后续有实现:tuple_size_v tuple_size::value和tuple_element_t tuple_element::type。 事例Example: auto tup std::tuple<in…...
Http代理与socks5代理有何区别?如何选择?(二)
上篇文章我们基本分别了解了http代理与socks5代理的定义与优缺点,接下来我们继续来了解http代理与socks5代理之间的比较与区别。 一、两者的比较 1、功能比较 HTTP代理专门用于Web流量,并在处理HTTP和HTTPS协议方面非常高效。它们可以修改正在传输的数…...
java中main方法和@Test注解的区别
Java的main方法和Test注解在用途和功能上有很大的区别。 main方法是Java应用程序的入口点。当你运行一个Java程序时,JVM会首先查找具有public static void main(String[] args)签名的类,并从这个方法开始执行程序。main方法通常用于控制程序的启动、执行…...
C++进阶语法——STL 标准模板库(下)(Standard Template Library)【学习笔记(七)】
文章目录 STL 代码示例1、迭代器2、算法3、array容器示例4、vector示例5、deque(double ended queue,双端数组)示例6、list(链表)容器7、set示例8、map示例9、stack 示例10、queue示例11、priority_queue (…...
力扣:求最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。 如果不存在公共前缀,返回空字符串 示例1: 输入: strs ["flower", "flow" , "flight"] 输出: "fl" 示例2: 输入: strs ["dog","racecar","car&…...
Redis入门04-消息通知
目录 Redis中的消息通知 命令行操作 Redis中的管道 Redis中的消息通知 Redis可以用作消息队列的中间件,它提供了一种轻量级、高性能的消息传递机制,适用于实时通信、任务队列、事件处理等各种应用。以下是有关如何使用Redis作为消息队列的一些重要信…...
关于idea使用的一些操作设置
关于idea使用的一些操作设置 1. 常用的一下设置1.1 快捷键相关1.2 配置自动生成注释(类、方法等)1.3 maven项目相关1.4 常见其他的一些操作设置 2. IntelliJ IDEA 取消param注释中参数报错提示3. idea同时打开多个文件,导航栏不隐藏、自动换行…...
CLion 2023.2.2(C ++ IDE智能代码编辑器)
CLion 2023是一款跨平台C/C集成开发环境(IDE)。它为Mac用户提供了高效的编程体验,帮助程序员们在Mac平台上进行C/C开发。 CLion 2023支持多种编译器和调试器,并具有强大的代码分析和导航功能。它还为用户提供了许多便捷的工具和插…...
企业级API资产如何管理
在当今数字化时代,API已成为企业开发和创新的重要工具,如何高效地管理和调度这些资产成为了企业发展的重要课题。API资产管理的出现,为企业解决了这一难题,通过合理管理和利用API资产,企业可以更好地推动业务发展&…...
Git https方式拉的代码IDEA推送代码报错
报错信息 fatal: could not read Username for ‘https://codehub-cn-south-1.devcloud.huaweicloud.com’: No such file or directory 18:18:39.885: [recovery_pattern] git -c credential.helper -c core.quotepathfalse -c log.showSignaturefalse push --progress --porc…...
C++ capacity()用法总结
1. 容器的容量 容器的size是指它已经保存的元素的数目;而capacity则是在不分配新的内存空间的前提下它最多可以保存多少元素。capacity(),size(),reserve(),resize()这几个都是不太容易区分的函数 functionmeancapacity()获得容…...
TensorFlow2.0教程1-Eager
文章目录 张量极其操作1 张量自定义层一、网络层layer的常见操作二、实现自定义网络层三、网络层组合自动求导一、Gradient tapes二、记录控制流三、高阶梯度自定义训练(基础)一、Variables二、示例:拟合线性模型1、定义模型2.定义损失函数3.获取训练数据4.定义训练循环张…...
Redis学习系统(持续更新中)
RedisExample 课程介绍 目标是提供一个高效、可靠的学习和实践Redis的环境。我们将通过搭建Redis集群、实现缓存数据的持久化存储、制定缓存数据的淘汰策略以及同步缓存数据等步骤来深入了解和学习Redis的特性和功能。通过这个项目,你可以掌握Redis的核心概念和技…...
el-select获取id和name
一般选中节点只会返回:value绑定的数据给v-model中,要想获取id和name一并传给后端,需要如下几步: 1、给选择框添加点击事件 input"selectChangeParent" 2、v-for中多添加一个参数 index <el-select v-model"inputForm.pr…...
最简单的驱动程序
简介 在 Linux 内核中,Makefile 和 Kconfig 是两个重要的文件,它们分别承担着不同的作用。 Makefile Makefile 是一个文本文件,用于定义编译和构建内核的规则。它使用 make 工具来管理和自动化构建过程。Makefile 定义了编译器、链接器、编译选项、目标文件、源文件等信息…...
MFC String类的初始化学习
之前写过CString的用法; VC CString 编程实例图解_bcbobo21cn, cstring-CSDN博客 下面单独看一下CString的各种初始化方式; void CTest2View::OnDraw(CDC* pDC) {CTest2Doc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for nati…...
vue项目使用vite设置proxy代理,vite.config.js配置,解决本地跨域问题
vue3vite4项目,配置代理实现本地开发跨域问题 非同源请求,也就是协议(protocol)、端口(port)、主机(host)其中一项不相同的时候,这时候就会产生跨域 vite的proxy代理和vue-cli的proxy大致相同,需要在vite.config.js文件中配置&…...
实用-----七牛云绑定自定义域名 配置 HTTPS
实用-----七牛云绑定自定义域名 配置 HTTPS(无废话 无尿点) 1.访问SSL证书购买页面 https://portal.qiniu.com/certificate/ssl 2.购买免费证书 3.补全信息 注意: 域名直接输入 无需 www座机号随意填 区号需要搜索 下面为示例 4. 直接确认…...
【TS篇三】类、函数、for-of循环、类型推断
文章目录 一、类1.1 基本示例1.2 继承1.3 实例成员访问修饰符1.3.1 public 开放的1.3.2 private 私有的1.3.3 protected 受保护的1.3.4 readonly 只读的1.3.5 在参数中使用修饰符 1.4 属性的存(get)取(set)器1.5 静态成员 二、函数…...
Chatgpt批量改写文章网页版可多开软件-自动登录换号生成word或者TXT
Chatgpt批量改写文章网页版可多开软件介绍: 1、改写后生成docx格式文档和生成txt文档二选一。 2、支持原来docx文档里带图片的改写,改写伪原创后的docx里也带图片。 3、软件可以设置是否开启标题改写,可以自定义标题改写指令。 4、可以设置…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
Zustand 状态管理库:极简而强大的解决方案
Zustand 是一个轻量级、快速和可扩展的状态管理库,特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
