tuple 简易实现(C++ 模板元编程)
std::tuple
在标准库里面,tuple主要有下面四个类模板 or 函数模板
- tuple
- tuple_size
- tuple_element
- get
在后续有实现: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、可以设置…...
 
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
 
【JavaEE】-- HTTP
1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...
 
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
 
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
 
微信小程序 - 手机震动
一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注:文档 https://developers.weixin.qq…...
 
江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...
 
图表类系列各种样式PPT模版分享
图标图表系列PPT模版,柱状图PPT模版,线状图PPT模版,折线图PPT模版,饼状图PPT模版,雷达图PPT模版,树状图PPT模版 图表类系列各种样式PPT模版分享:图表系列PPT模板https://pan.quark.cn/s/20d40aa…...
 
以光量子为例,详解量子获取方式
光量子技术获取量子比特可在室温下进行。该方式有望通过与名为硅光子学(silicon photonics)的光波导(optical waveguide)芯片制造技术和光纤等光通信技术相结合来实现量子计算机。量子力学中,光既是波又是粒子。光子本…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
