c++之元组std::tuple常见用法
元组,c++11中引入的新的类型,可类比std::pair。 但是std::pair只能支持两个元素。 理论上, 元组支持0~任意个元素。
本文演示环境: VS2015 up3
0、头文件
- #include <tuple>
1、创建和初始化
1.1、创建一个空的元组, 创建时,需要指定元组的数据类型。
- std::tuple<int, float, double, long, long long> first;
1.2 、创建一个元组并初始化元组。
- 1 std::string str_second_1("_1");
- 2 std::string str_second_2("_2");
- 3
- 4 // 指定了元素类型为引用 和 std::string, 下面两种方式都是可以的,只不过第二个参数不同而已
- 5 std::tuple<std::string, std::string> second_1(str_second_1, std::string("_2"));
- 6 std::tuple<std::string, std::string> second_2(str_second_1, str_second_2);
1.3、创建一个元素是引用的元组
- 1 //3、创建一个元组,元组的元素可以被引用, 这里以 int 为例
- 2 int i_third = 3;
- 3 std::tuple<int&> third(std::ref(i_third));
1.4、使用make_tuple创建元组
- 1 int i_fourth_1 = 4;
- 2 int i_fourth_2 = 44;
- 3 // 下面的两种方式都可以
- 4 std::tuple<int, int> forth_1 = std::make_tuple(i_fourth_1, i_fourth_2);
- 5 auto forth_2 = std::make_tuple(i_fourth_1, i_fourth_2);
1.5、创建一个类型为引用的元组, 对元组的修改。 这里以 std::string为例
- 1 std::string str_five_1("five_1");
- 2 // 输出原址值
- 3 std::cout << "str_five_1 = " << str_five_1.c_str() << "\n";
- 4
- 5 std::tuple<std::string&, int> five(str_five_1, 5);
- 6 // 通过元组 对第一个元素的修改,str_five_1的值也会跟着修改,因为元组的第一个元素类型为引用。
- 7 // 使用get访问元组的第一个元素
- 8 std::get<0>(five) = "five_2";
- 9
- 10 // 输出的将是: five_2
- 11 std::cout << "str_five_1 = " << str_five_1.c_str() << "\n";
输出结果(VS2015 up3输出):
2、计算元组的元素个数
需要函数: std::tuple_size。 下面是一个例子,
- 1 std::tuple<char, int, long, std::string> first('A', 2, 3, "4");
- 2 // 使用std::tuple_size计算元组个数
- 3 int i_count = std::tuple_size<decltype(first)>::value;
- 4 std::cout << "元组个数=" << i_count << "\n";
输出结果:
3、访问元素
访问元组的元素,需要函数: std::get<index>(obj)。其中:【index】是元组中元素的下标,0 ,1 , 2, 3, 4,.... 【obj】-元组变量。
一个例子:
- 1 std::tuple<char, int, long, std::string> second('A', 2, 3, "4");
- 2 int index = 0;
- 3 std::cout << index++ << " = " << std::get<0>(second) << "\n";
- 4 std::cout << index++ << " = " << std::get<1>(second) << "\n";
- 5 std::cout << index++ << " = " << std::get<2>(second) << "\n";
- 6 std::cout << index++ << " = " << std::get<3>(second).c_str() << "\n";
输出结果:
【注意】元组不支持迭代访问, 且只能通过索引(或者tie解包:将元组的中每一个元素提取到指定变量中)访问, 且索引不能动态传入。上面的代码中,索引都是在编译器编译期间就确定了。 下面的演示代码将会在编译期间出错。
- for (int i = 0; i < 3; i++)
- std::cout << index++ << " = " << std::get<i>(second) << "\n"; // 无法通过编译
4、获取元素的类型
获取元组中某个元素的数据类型,需要用到另外一个类型: std::tuple_element 。 语法: std::tuple_element<index, tuple> 。 【index】-元组中元素的索引,【tuple】哪一个元组
一个例子:
- 1 std::tuple<int, std::string> third(9, std::string("ABC"));
- 2
- 3 // 得到元组第1个元素的类型,用元组第一个元素的类型声明一个变量
- 4 std::tuple_element<1, decltype(third)>::type val_1;
- 5
- 6 // 获取元组的第一个元素的值
- 7 val_1 = std::get<1>(third);
- 8 std::cout << "val_1 = " << val_1.c_str() << "\n";
输出结果:
用获取元组第一个元素的类型声明了一个变量,再对变量赋值。
5、使用 std::tie解包
元组,可以看作一个包,类比结构体。 需要访问元组的元素时,2 种方法: A、索引访问,B、std::tie 。
元组包含一个或者多个元素,使用std::tie解包: 首先需要定义对应元素的变量,再使用tie。 比如,元素第0个元素的类型时 char, 第1个元素类型时int, 那么, 需要定义 一个 char的变量和int的变量, 用来储存解包元素的结果。
一个例子:
- 1 std::tuple<char, int, long, std::string> fourth('A', 2, 3, "4");
- 2
- 3 // 定义变量,保存解包结果
- 4 char tuple_0 = '0';
- 5 int tuple_1 = 0;
- 6 long tuple_2 = 0;
- 7 std::string tuple_3("");
- 8
- 9 // 使用std::tie, 依次传入对应的解包变量
- 10 std::tie(tuple_0, tuple_1, tuple_2, tuple_3) = fourth;
- 11
- 12 // 输出解包结果
- 13 std::cout << "tuple_0 = " << tuple_0 << "\n";
- 14 std::cout << "tuple_1 = " << tuple_1 << "\n";
- 15 std::cout << "tuple_2 = " << tuple_2 << "\n";
- 16 std::cout << "tuple_3 = " << tuple_3.c_str() << "\n";
输出结果:
说到 std::tie , 看下 VS2015 up3中的定义:
- 1 template<class... _Types> inline
- 2 constexpr tuple<_Types&...>
- 3 tie(_Types&... _Args) _NOEXCEPT
- 4 { // make tuple from elements
- 5 typedef tuple<_Types&...> _Ttype;
- 6 return (_Ttype(_Args...));
- 7 }
接着 std::tie 解包。 如果一个元组,只需要取出其中特定位置上的元素,不用把每一个元素取出来, 怎么做?
比如: 只要索引为 偶数的元素。
元组提供了类似占位符的功能: std::ignore 。满足上面的需求,只需要在索引为奇数的位置填上 std::ignore 。 一个例子:
- 1 std::tuple<char, int, long, std::string> fourth('A', 2, 3, "4");
- 2
- 3 // 定义变量,保存解包结果
- 4 char tuple_0 = '0';
- 5 int tuple_1 = 0;
- 6 long tuple_2 = 0;
- 7 std::string tuple_3("");
- 8
- 9 // 使用占位符
- 10 std::tie(tuple_0, std::ignore, tuple_2, std::ignore) = fourth;
- 11
- 12 // 输出解包结果
- 13 std::cout << "tuple_0 = " << tuple_0 << "\n";
- 14 std::cout << "tuple_1 = " << tuple_1 << "\n";
- 15 std::cout << "tuple_2 = " << tuple_2 << "\n";
- 16 std::cout << "tuple_3 = " << tuple_3.c_str() << "\n";
输出结果:
6、元组连接(拼接)
使用 std::tuple_cat 执行拼接
一个例子:
- 1 std::tuple<char, int, double> first('A', 1, 2.2f);
- 2
- 3 // 组合到一起, 使用auto, 自动推导
- 4 auto second = std::tuple_cat(first, std::make_tuple('B', std::string("-=+")));
- 5 // 组合到一起,可以知道每一个元素的数据类型时什么 与 auto推导效果一样
- 6 std::tuple<char, int, double, char, std::string> third = std::tuple_cat(first, std::make_tuple('B', std::string("-=+")));
- 7
- 8 // 输出合并后的元组内容
- 9 int index = 0;
- 10 std::cout << index++ << " = " << std::get<0>(second) << "\n";
- 11 std::cout << index++ << " = " << std::get<1>(second) << "\n";
- 12 std::cout << index++ << " = " << std::get<2>(second) << "\n";
- 13
- 14 std::cout << index++ << " = " << std::get<3>(second) << "\n";
- 15 std::cout << index++ << " = " << std::get<4>(second).c_str() << "\n";
输出结果:
7、遍历
这里将采用的时 递归遍历,需要注意,考虑爆栈的情况。其实,tuple也是基于模板的STL容器。 因为其可以容纳多个参数,且每个参数类型可不相同,遍历输出则涉及到参数展开的情况,这里以递归的方式实现遍历, 核心代码:
- 1 template<typename Tuple, size_t N>
- 2 struct tuple_show
- 3 {
- 4 static void show(const Tuple &t, std::ostream& os)
- 5 {
- 6 tuple_show<Tuple, N - 1>::show(t, os);
- 7 os << ", " << std::get<N - 1>(t);
- 8 }
- 9 };
- 10
- 11
- 12 // 偏特性,可以理解为递归的终止
- 13 template<typename Tuple>
- 14 struct tuple_show < Tuple, 1>
- 15 {
- 16 static void show(const Tuple &t, std::ostream &os)
- 17 {
- 18 os << std::get<0>(t);
- 19 }
- 20 };
- 21
- 22
- 23
- 24 // 自己写个函数,调用上面的递归展开,
- 25 template<typename... Args>
- 26 std::ostream& operator << (std::ostream &os, const std::tuple<Args...>& t)
- 27 {
- 28 os << "[";
- 29 tuple_show<decltype(t), sizeof...(Args)>::show(t, os);
- 30 os << "]";
- 31
- 32 return os;
- 33 }
调用示例:
- 1 auto t1 = std::make_tuple(1, 'A', "-=+", 2);
- 2 std::cout << t1;
输出结果:
c++之元组std::tuple常见用法的更多相关文章
- python map 常见用法
python map 常见用法2017年02月01日 19:32:41 淇怪君 阅读数:548版权声明:欢迎转载,转载请注明出处 https://blog.csdn.net/Tifficial/art ...
- 27.Python列表(list)、元组(tuple)、字典(dict)和集合(set)详解
本章将会介绍 Python 内置的四种常用数据结构:列表(list).元组(tuple).字典(dict)以及集合(set). 这四种数据结构一但都可用于保存多个数据项,这对于编程而言是非常重要的,因 ...
- python中os模块和sys模块的常见用法
OS模块的常见用法 os.remove() 删除文件 os.rename() 重命名文件 os.walk() 生成目录树下的所有文件名 os.chdir() 改变目录 os.mkd ...
- python3 字典常见用法总结
python3 字典常见用法总结 Python字典是另一种可变容器模型,且可存储任意类型对象,如字符串.数字.元组等其他容器模型. 一.创建字典 字典由键和对应值成对组成.字典也被称作关联数组或哈希表 ...
- Python基础数据类型-列表(list)和元组(tuple)和集合(set)
Python基础数据类型-列表(list)和元组(tuple)和集合(set) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 本篇博客使用的是Python3.6版本,以及以后分享的 ...
- C++的string类常见用法
C++的string常见用法,在网上看到一篇,但是不能在c++11编译器下运行,我修改了下,还没改完: #include<iostream> #include<string> ...
- std::tuple
tuple,元组类型.头文件<tuple>,tuple是一个固定大小的不同类型(异质,heterogeneous)值的集合(这一点是tuple与其他常规STL容器的最大不同,即它可以同时存 ...
- STL pair 常见用法详解
<算法笔记>学习笔记 pair 常见用法详解 //pair是一个很实用的"小玩意",当想要将两个元素绑在一起作为一个合成元素, //又不想因此定义结构体时,使用pair ...
- STL stack 常见用法详解
<算法笔记>学习笔记 stack 常见用法详解 stack翻译为栈,是STL中实现的一个后进先出的容器.' 1.stack的定义 //要使用stack,应先添加头文件#include &l ...
随机推荐
- python检验代理ip是否可用、代理ip检验
python检验代理ip是否可用.代理ip检验 安装相关模块: pip install requests 验证代理IP是否可用脚本: import random import telnetlib im ...
- python-django-请求响应对象
用户请求终端的信息: 包括使用的ip地址,浏览器类型等 cookie: 测试测试: def print_request(request): print(request) print("!!! ...
- MacBookpro安装VMware Fusion虚拟机,并安装win7 64位系统
1.准备好安装用的东西(准备好正确的东西,安装路上就成功了一半)(1)VMware Fusion 附带注册机生成注册码,链接: https://pan.baidu.com/s/13Qm9zPOFjFt ...
- Pytorch学习笔记08----优化器算法Optimizer详解(SGD、Adam)
1.优化器算法简述 首先来看一下梯度下降最常见的三种变形 BGD,SGD,MBGD,这三种形式的区别就是取决于我们用多少数据来计算目标函数的梯度,这样的话自然就涉及到一个 trade-off,即参数更 ...
- Shell 统计文件的行数
目录 统计文件的行数 题目 题解-awk 题解-wc 题解sed 统计文件的行数 题目 写一个 bash脚本以输出一个文本文件 nowcoder.txt中的行数 示例: 假设 nowcoder.txt ...
- UBI 文件系统之分区挂载
Linux 系统中有关mtd和ubi的接口:(1) cat /proc/mtd:可以看到当前系统的各个mtd情况,(2) cat /proc/partitions: 分区信息,有上面的类似(3) ca ...
- Spark基础:(三)Spark 键值对操作
1.pair RDD的简介 Spark为包含键值对类型的RDD提供了一些专有的操作,这些RDD就被称为pair RDD 那么如何创建pair RDD呢? 在不同的语言中有着不同的创建方式 在pytho ...
- 零基础学习java------20---------反射
1. 反射和动态代理 参考博文:https://blog.csdn.net/sinat_38259539/article/details/71799078 1.0 什么是Class: 我们都知道,对象 ...
- Android项目的settings.gradle和build.gradle
gradle构建的项目中的build.gradle和settings.gradle文件 build.gradle 浅析(一) 史上最全的Android build.gradle配置教程 Android ...
- 【Java 基础】Java Map中的Value值如何做到可以为任意类型的值
Occasionally the average developer runs into a situation where he has to map values of arbitrary typ ...