C++ | std::tuple

news2025/4/7 8:57:24

std::tuple


文章目录

  • std::tuple
    • 成员函数及非成员函数
      • 模板参数
      • 成员函数
      • Non-member functions非成员函数
      • 辅助类
    • 构造函数
    • 获取元祖元素值
    • 元素个数
    • 元素的类型
    • Reference

类模板 std::tuple 是不同类型值的固定大小集合。 它是 std::pair 的泛化。
可以当做一个结构体使用 ,不需要创建结构体就能获得结构体的特征

std::tuple理论上可以有无数个任意类型的成员变量,而std::pair只能是2个成员,因此在需要保存3个及以上的数据时就需要使用tuple元组了

直观感受一下:

#include <iostream>
#include <tuple>
int main(int argc, char **argv) {

  typedef std::tuple<int, double, int, double> Randy;

  Randy q0(0, 1, 2, 3);
  // display contents " 0 1 2 3"
  std::cout << " " << std::get<0>(q0);
  std::cout << " " << std::get<1>(q0);
  std::cout << " " << std::get<2>(q0);
  std::cout << " " << std::get<3>(q0);
  std::cout << std::endl;

  Randy q1;
  q1 = q0;
  // display contents " 0 1 2 3"
  std::cout << " " << std::get<0>(q1);
  std::cout << " " << std::get<1>(q1);
  std::cout << " " << std::get<2>(q1);
  std::cout << " " << std::get<3>(q1);
  std::cout << std::endl;

  std::tuple<char, int> q2(std::make_pair('x', 4));
  // display contents " x 4"
  std::cout << " " << std::get<0>(q2);
  std::cout << " " << std::get<1>(q2);
  std::cout << std::endl;

  Randy q3(q0);
  // display contents " 0 1 2 3"
  std::cout << " " << std::get<0>(q3);
  std::cout << " " << std::get<1>(q3);
  std::cout << " " << std::get<2>(q3);
  std::cout << " " << std::get<3>(q3);
  std::cout << std::endl;

  typedef std::tuple<int, float, int, float> Randy2;

  Randy q4(Randy2(4, 5, 6, 7));
  // display contents " 4 5 6 7"
  std::cout << " " << std::get<0>(q4);
  std::cout << " " << std::get<1>(q4);
  std::cout << " " << std::get<2>(q4);
  std::cout << " " << std::get<3>(q4);
  std::cout << std::endl;

  return (0);
}

result:

 0 1 2 3
 0 1 2 3
 x 4
 0 1 2 3
 4 5 6 7

成员函数及非成员函数

模板参数

Types…-元组存储的元素的类型。 支持空列表。

成员函数

(constructor)(C++11)构造一个新的“元组”(公共成员函数)
operator=(C++11)将一个“元组”的内容分配给另一个(公共成员函数)
swap(C++11)交换两个元组的内容(公共成员函数)

Non-member functions非成员函数

make_tuple(C++11)创建由参数类型(函数模板)定义的类型的“元组”对象
tie(C++11)创建左值引用的元组或将元组解包为单个对象(函数模板)
forward_as_tuple(C++11)创建 forwarding references 的“元组”(函数模板)
tuple_cat(C++11)通过连接任意数量的元组(函数模板)创建一个“元组”
std::get(std::tuple)(C++11)元组访问指定元素(函数模板)
operator==operator!=operatoroperator>=operator<=>(removed in C++20)
(removed in C++20)(removed in C++20)(removed in C++20)(removed in C++20)(C++20)
按字典顺序比较元组中的值(函数模板)
std::swap(std::tuple)(C++11)特化 std::swap 算法(函数模板)

辅助类

std::tuple_size(C++11)在编译时获得 tuple 的大小(类模板特化)
std::tuple_element(C++11)获得指定元素的类型(类模板特化)
std::uses_allocator(C++11)特化 std::uses_allocator 类型特征(类模板特化)
std::basic_common_reference<tuple-like>(C++23)确定“元组”和类元组类型的公共引用类型(类模板特化)
std::common_type<tuple-like>(C++23)确定“元组”的通用类型和类元组类型(类模板特化)
ignore(C++11)使用 tie 解压 tuple 时跳过元素的占位符(常量)

构造函数

#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>
 
// 将向量打印到流的辅助函数
template<class Os, class T>
Os& operator<< (Os& os, std::vector<T> const& v)
{
    os << '{';
    for (auto i{v.size()}; const T& e : v)
        os << e << (--i ? "," : "");
    return os << '}';
}
 
template<class T>
void print_single(T const& v)
{
    if constexpr (std::is_same_v<T, std::decay_t<std::string>>)
        std::cout << std::quoted(v);
    else if constexpr (std::is_same_v<std::decay_t<T>, char>)
        std::cout << "'" << v << "'";
    else
        std::cout << v;
}
 
// 打印任意大小的元组的辅助函数
template<class Tuple, std::size_t N>
struct TuplePrinter {
    static void print(const Tuple& t)
    {
        TuplePrinter<Tuple, N-1>::print(t);
        std::cout << ", ";
        print_single(std::get<N-1>(t));
    }
};
 
template<class Tuple>
struct TuplePrinter<Tuple, 1>{
    static void print(const Tuple& t)
    {
        print_single(std::get<0>(t));
    }
};
 
template<class... Args>
void print(const std::tuple<Args...>& t)
{
    std::cout << "(";
    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
    std::cout << ")\n";
}
// 辅助函数结束
 
int main()
{
    std::tuple<int, std::string, double> t1;
    std::cout << "Value-initialized, t1: "; 
    print(t1);
    
    std::tuple<int, std::string, double> t2{42, "Test", -3.14};
    std::cout << "Initialized with values, t2: "; 
    print(t2);
    
    std::tuple<char, std::string, int> t3{t2};
    std::cout << "Implicitly converted, t3: "; 
    print(t3);
    
    std::tuple<int, double> t4{std::make_pair(42, 3.14)};
    std::cout << "Constructed from a pair, t4: ";
    print(t4);
 
    // 给定的分配器 my_alloc 具有单参数构造函数
    // my_alloc(int); 使用 my_alloc(1) 在向量中分配 5 个整数
    using my_alloc = std::allocator<int>;
    std::vector<int, my_alloc> v { 5, 1, my_alloc{/*1*/} };
    
    // 使用 my_alloc(2) 在元组的向量中分配 5 个整数
    std::tuple<int, std::vector<int, my_alloc>, double> t5{
        std::allocator_arg, my_alloc{/*2*/}, 42, v, -3.14};
    std::cout << "Constructed with allocator, t5: ";
    print(t5);
}

结果:

Value-initialized, t1: (0, "", 0)
Initialized with values, t2: (42, "Test", -3.14)
Implicitly converted, t3: ('*', "Test", -3)
Constructed from a pair, t4: (42, 3.14)
Constructed with allocator, t5: (42, {1,1,1,1,1}, -3.14)

获取元祖元素值

#include <tuple>
#include <iostream>
#include <string>
#include <stdexcept>
 
std::tuple<double, char, std::string> get_student(int id)
{
    switch (id)
    {
        case 0: return {2.13, 'A', "Randy Simpson"};
        case 1: return {2.9, 'C', "Milhouse Sesame"};
        case 2: return {1.22, 'D', "Kim Wiggum"};
        case 3: return {0.6, 'F', "SanJie JiYuan"};
    }
 
    throw std::invalid_argument("id");
}
 
int main()
{
    const auto student0 = get_student(0);
    std::cout << "ID: 0, "
              << "GPA: " << std::get<0>(student0) << ", "
              << "grade: " << std::get<1>(student0) << ", "
              << "name: " << std::get<2>(student0) << '\n';
 
    const auto student1 = get_student(1);
    std::cout << "ID: 1, "
              << "GPA: " << std::get<double>(student1) << ", "
              << "grade: " << std::get<char>(student1) << ", "
              << "name: " << std::get<std::string>(student1) << '\n';
 
    double gpa2;
    char grade2;
    std::string name2;
    std::tie(gpa2, grade2, name2) = get_student(2);
    std::cout << "ID: 2, "
              << "GPA: " << gpa2 << ", "
              << "grade: " << grade2 << ", "
              << "name: " << name2 << '\n';
 
    // C++17 structured binding:
    const auto [ gpa3, grade3, name3 ] = get_student(3);
    std::cout << "ID: 3, "
              << "GPA: " << gpa3 << ", "
              << "grade: " << grade3 << ", "
              << "name: " << name3 << '\n';
}

结果:

ID: 0, GPA: 2.13, grade: A, name: Randy Simpson
ID: 1, GPA: 2.9, grade: C, name: Milhouse Sesame
ID: 2, GPA: 1.22, grade: D, name: Kim Wiggum
ID: 3, GPA: 0.6, grade: F, name: SanJie JiYuan

元素个数

  std::tuple<int, char, double> randy (2, 'san_jie_ji_yuan', 0.13);
 
  std::cout << std::tuple_size<decltype(randy)>::value;

结果: 3

元素的类型

std::tuple<std::string, int> tq("Randy", 213);
  
std::tuple_element<1, decltype(tq)>::type sesames;  

sesames = std::get<1>(tq);

std::cout << "sesames: " << sesames << std::endl;

结果:sesames: 213

Reference

  • std::tuple

欢迎关注公众号【三戒纪元】

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/514331.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【ChatGPT】科技革命促生互联网时代 ChatGPT浪潮打乱时代布局 人工智能新时代下的发展前景

目录 科技革命促生互联网时代 科技进步伴随着大国崛起 科技革命的发展 互联网时代的到来 ChatGPT浪潮来袭 资本市场当前的热潮 人工智能新时代下我们何去何从 开放注册两个月用户数破亿&#xff0c;ChatGPT的爆火也标志着时代的浪潮将要来袭&#xff0c;由科技革命促生的…

C语言200行代码实现简易三子棋

前言 三子棋应该是是我们最早接触到的棋类游戏&#xff0c;用C语言实现三子棋对初学者来说是一种不错的锻炼 编写三子棋只需要用到数组、函数和生成随机数的知识&#xff0c;所以比较适合成为编程学习者编写的第一个小游戏。 一.代码实现 第一部分是源码复制就可以使用&…

WiFi(Wireless Fidelity)基础(六)

目录 一、基本介绍&#xff08;Introduction&#xff09; 二、进化发展&#xff08;Evolution&#xff09; 三、PHY帧&#xff08;&#xff08;PHY Frame &#xff09; 四、MAC帧&#xff08;MAC Frame &#xff09; 五、协议&#xff08;Protocol&#xff09; 六、安全&#x…

未面试蓄力,redis肝起来

目录 1、为什么要使用Redis做缓存&#xff1f;2、为什么Redis单线程模型效率也能那么高&#xff1f;3、Redis6.0为什么要引入多线程呢&#xff1f;4、Redis常见数据结构以及使用场景字符串&#xff08;String&#xff09;哈希(Hash)列表&#xff08;list&#xff09;集合&#…

【前端提效】--Chrome浏览器开发者工具 DevTools 使用技巧

介绍一下 DevTools 的一些好用的技巧&#xff0c;它能够很好地帮助你提高生产力和解决问题的能力。 1、打开命令行 或者使用&#xff1a;快捷键 Ctrl Shift P (Mac&#xff1a; ⌘ Shift P ) 命令行可以做很多事情&#xff0c;包括但不限于截图、更换主题等 2、控制 DevT…

Inno Setup Compiler的安装和使用详解

安装&#xff1a;官网最新下载最新版 最新版不支持中文哈&#xff0c;安装的时候直接选英文就好 安装注意事项&#xff1a;在安装过程中有一个 询问是否要 安装一个加密版本的&#xff08;可根据自己的需求挑选–我就没有&#xff09; 使用&#xff1a; 1.打开应用程序进入到…

【微信小程序】微信小程序的接口调入 获取太阳码 根据返回值的类型进行接收,微信接口可能直接返回图片,也可能返回一个错误信息的json,同时兼容处理这两种情况

目录 事件起因环境和工具操作过程解决办法遇到的一点问题结束语 事件起因 在开发一个关于微信小程序的过程中&#xff0c;有一个这样的需求&#xff0c;要求生成微信小程序的太阳码&#xff0c;然而这个东西的请求方式我们是这样的&#xff1a;我作为后端服务去请求这个太阳码…

【MFAC】基于紧格式动态线性化的无模型自适应控制(Matlab代码)

例题来源&#xff1a;侯忠生教授的《无模型自适应控制&#xff1a;理论与应用》&#xff08;2013年科学出版社&#xff09;。 &#x1f449;对应书本 4.2 单输入单输出系统(SISO)紧格式动态线性化(CFDL)的无模型自适应控制(MFAC) 例题4.1 题目要求 matlab代码 clc; clear al…

ASEMI代理ADXL345BCCZ-RL7原装ADI车规级ADXL345BCCZ-RL7

编辑&#xff1a;ll ASEMI代理ADXL345BCCZ-RL7原装ADI车规级ADXL345BCCZ-RL7 型号&#xff1a;ADXL345BCCZ-RL7 品牌&#xff1a;ADI /亚德诺 封装&#xff1a;LGA-14 批号&#xff1a;2023 安装类型&#xff1a;表面贴装型 引脚数量&#xff1a;14 工作温度:-55C~105C…

HTTPS连接建立过程

目录 前言什么是HTTPSHTTPS的作用 TLS建立连接过程1、TCP三次握手2、Client Hello3、Sever Hello4、校验数字证书5、客户端回应6、服务器回应7、TCP四次挥手 前言 什么是HTTPS HTTPS&#xff0c;Hyper Text Transfer Protocol over SecureSocket Layer&#xff0c;超文本传输…

「自动化」聊起来简单,做起来难 | 谈效风生

第4期&#xff1a;“自动化”聊起来简单&#xff0c;做起来难 在上一期《如何找到现有研发体系的「内耗问题」?》中&#xff0c;我们聊了评估现有研发体系&#xff0c;正确的找到“体系内耗问题”&#xff0c;是改变研发体系的第一步。本期我们继续聊下一个关键点就是研发体系…

MIT6.824 lab4B实验记录

Background 主要是完成一个可以根据group数量&#xff0c;动态调整shard所属的group的分布式kv键值引擎。其中shard->group的配置由shardctrler集群来管理&#xff0c;底层也是通过raft group来容错&#xff08;分布式嘛&#xff09; 然后这个shardkv就是要完成的是根据sh…

哪些地方能发表计算机论文? - 易智编译EaseEditing

计算机科学领域是一个快速发展的领域&#xff0c;每年都会涌现出许多新的科技和新的研究成果。 为了保证研究成果的质量和可信度&#xff0c;科学家们通常会通过期刊来发表自己的研究成果。 SCI期刊是世界著名的科技期刊数据库&#xff0c;被认为是科技领域内的权威数据库之一…

docker 系列之 Dockerfile 文件里 cmd命令与entrypoint命令区别

文章目录 一、cmd&#xff1a;用法1&#xff1a;带有中括号的形式用法2&#xff1a;shell form&#xff0c;即没有中括号的形式 二、entrypoint&#xff1a;第一种&#xff1a;命令行模式&#xff0c;也就是带中括号第二种&#xff1a;shell模式 三、总结&#xff1a; 一、cmd&…

《人月神话》纪念典藏版撤下了以前的宣传语

DDD领域驱动设计批评文集>> 《软件方法》强化自测题集>> 《软件方法》各章合集>> 《人月神话》作者Frederick Phillips Brooks Jr. 于2022年11月17日逝世。 清华大学出版社近期将发行《人月神话》纪念典藏版。 新版的封底如下&#xff0c;宣传语更换成了…

CleanMyMac X4.13.2.dmg最新中文版下载

它是Mac上一款美观易用的系统优化清理工具&#xff0c;也是小编刚开始用Mac时的装机必备。它能够清理系统垃圾&#xff0c;提升电脑的运行速度&#xff0c;卸载许久不用的软件&#xff0c;使其变得如新机一般流畅。 CleanMyMac X是一款专业的Mac清理软件&#xff0c;可智能清理…

al智能改写工具-ai自动生成文章软件

随着互联网的发展&#xff0c;文章编辑在不断地向自动化、高效化方向进行转变&#xff0c;一款名叫“改稿神器”的工具应运而生。它可以帮助我们快速实现全自动批量改稿&#xff0c;做到没有错别字&#xff0c;自动优化语法&#xff0c;自动插入图片&#xff0c;严格按照标准的…

【腾讯云FinOps Crane 集训营】初识 FinOps Crane

前言&#xff1a; 有幸参加了腾讯云Finops Crane 集训营&#xff0c;学到了很多东西&#xff0c;现在将内容分享给大家。 Finops Crane &#xff1a;是一个基于 FinOps 的云资源分析与成本优化平台。 它的目标是希望在保证客户应用运行质量的前提下&#xff0c;实现极致的降本。…

web前端面试题汇总大全 -- 持续更新!

文章目录 一、html 系列 ⭐⭐⭐⭐⭐1、H5新增特性和css3新增特性&#xff1f; 二、css 系列 ⭐⭐⭐⭐⭐1、BFC的理解&#xff1f;2、说说你对盒模型的理解&#xff1f;3、如何实现元素⽔平垂直居中&#xff1f;4、CSS如何画⼀个三⻆形&#xff1f;原理是什么&#xff1f;5、说说…

二分查找基础篇-JAVA

文章目录 前言 大家好,我是最爱吃兽奶,这篇博客给大家介绍一下二分查找,我们先从最基本的开始讲解,再慢慢深入,把优化和变形也和大家说一下,那么,跟着我的步伐,我们一起去看看吧! 一、什么是二分查找? 二分查找(Binary Search)也称作折半查找 二分查找的效率很高,每查找一次…