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

tuple 简易实现(C++ 模板元编程)

std::tuple

在标准库里面,tuple主要有下面四个类模板 or 函数模板

  • tuple
  • tuple_size
  • tuple_element
  • get

在后续有实现:tuple_size_v = tuple_size::valuetuple_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

http://www.lryc.cn/news/216723.html

相关文章:

  • Http代理与socks5代理有何区别?如何选择?(二)
  • java中main方法和@Test注解的区别
  • C++进阶语法——STL 标准模板库(下)(Standard Template Library)【学习笔记(七)】
  • 力扣:求最长公共前缀
  • Redis入门04-消息通知
  • 关于idea使用的一些操作设置
  • CLion 2023.2.2(C ++ IDE智能代码编辑器)
  • 企业级API资产如何管理
  • Git https方式拉的代码IDEA推送代码报错
  • C++ capacity()用法总结
  • TensorFlow2.0教程1-Eager
  • Redis学习系统(持续更新中)
  • el-select获取id和name
  • 最简单的驱动程序
  • MFC String类的初始化学习
  • vue项目使用vite设置proxy代理,vite.config.js配置,解决本地跨域问题
  • 实用-----七牛云绑定自定义域名 配置 HTTPS
  • 【TS篇三】类、函数、for-of循环、类型推断
  • Chatgpt批量改写文章网页版可多开软件-自动登录换号生成word或者TXT
  • Modelsim 使用教程(4)—— Working With Multiple Libraries
  • 【重要】浏览器输入地址提示【您的连接不是私密连接】解决方法
  • ESP-07S烧写固件记录
  • 网络编程中关于UDP套接字的一些知识点
  • 淘宝商品评论API接口(评论内容|日期|买家昵称|追评内容|评论图片|评论视频..)
  • 计算机网络 第五章传输层
  • cartographer,ros,路径规划近两年的工作笔记
  • react 生命周期讲解
  • 什么是TCY油封?
  • 【Vue.js】使用Element入门搭建登入注册界面axios中GET请求与POST请求跨域问题
  • Apache Hive