广告位联系
返回顶部
分享到

C++11, 14, 17对tuple元素的访问介绍

C语言 来源:未知 作者:佚名 发布时间:2022-11-06 19:04:53 人浏览
摘要

C++11, 14, 17对tuple元素的访问 std::tuple 作为可以存放任意个数,任意类型的元祖被我个人经常使用。 记得以前看侯捷谈到这个数据结构的时候,被他的实现所惊奇,太巧妙地设计。 我自

C++11, 14, 17对tuple元素的访问

std::tuple 作为可以存放任意个数,任意类型的元祖被我个人经常使用。

记得以前看侯捷谈到这个数据结构的时候,被他的实现所惊奇,太巧妙地设计。

我自己在使用std::tuple的时候也随着C++版本的更新尝试新的写法,对于元组中元素的获取,我一直觉得很有意思:

比如我有这么一个源文件:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

#include <iostream>

#include <tuple>

 

#define CPP11 (__cplusplus < 201401L)

#define CPP14 (__cplusplus < 201701L and __cplusplus > 201401L)

#define CPP17 (__cplusplus >= 201702L)

 

class Moo {

  Moo() { ::printf("%s\n", __PRETTY_FUNCTION__); }

  Moo(Moo const &) { ::printf("%s\n", __PRETTY_FUNCTION__); }

  Moo(Moo &&) { ::printf("%s\n", __PRETTY_FUNCTION__); }

  Moo &operator=(Moo const &) noexcept {

    ::printf("%s\n", __PRETTY_FUNCTION__);

    return *this;

  }

 

  Moo &operator=(Moo &&) noexcept {

    ::printf("%s\n", __PRETTY_FUNCTION__);

    return *this;

  }

 

  ~Moo() { ::printf("%s\n", __PRETTY_FUNCTION__); }

};

 

int main() {

  std::cout << "c++ version:" << __cplusplus << std::endl;

  auto &&tp = std::make_tuple<Moo, const char *, int>(Moo(), "hello world", 3);

 

#if CPP11

  auto &&first = std::get<0>(tp);

  auto &&second = std::get<1>(tp);

  auto &&third = std::get<2>(tp);

#endif

 

#if CPP14

  auto &&first = std::get<Moo>(tp);

  auto &&second = std::get<const char *>(tp);

  auto &&third = std::get<int>(tp);

#endif

 

#if CPP17

  auto [a, b, c] = tp;

  auto &[first, second, third] = tp;

#endif

 

  return 0;

}

Moo类考察当前对象在构造tuple和返回值的过程中经历怎样的人生

  • C++11: 使用std::get方法来获取对应秩的元素的引用
  • C++14: 使用类似在nlohmannjson里面获取对应类型的json对象的方式,通过类型来获取对应的元素的引用,有点现代C++那味儿了吼
  • C++17: 引入了结构化绑定,不实用引用的时候会返回新创建的临时对象,a, b, c是对临时对象的右值引用,而使用引用则是想std::get那样引用原本对象。C++17结构化绑定yyds!表达力比之前强太多

std::tuple大总结

C++11引入了一个新的较实用的模板类型,std::tuple,也即是元组。元组是一个固定大小的不同类型(异质,heterogeneous)值的集合,也即它可以同时存放不同类型的数据。F11 - 专业站长和开发者的学习网站(www.f11.cn)

类似于python中用小括号表示的元组类型。C++已有的std::pair类型类似于一个二元组,可看作是std::tuple的一个特例,std::tuple也可看作是std::pair的泛化。std::pair的长度限制为2,而std::tuple的元素个数为0~任意个。

元组的使用

  • 有时候希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,std::tuple是非常有用的。我们可以将std::tuple看作一个“快速而随意”的数据结构。我们可以把它当作一个通用的结构体使用,但又不需要创建和获取结构体的特征,使得程序更加简洁直观。
  • 创建一个std::tuple对象时,可以使用tuple的默认构造函数,它会对每个成员进行值初始化;也可以为每个成员提供一个初始值,此时的构造函数是explicit的,因此必须使用直接初始化方法。
  • 一个std::tuple类型的成员数目是没有限制的,因此,元组的成员都是未命名的。要访问一个元组的成员,就要使用一个名为get的标准库函数模板。为了使用get,我们必须指定一个显式模板实参,它指出我们想要访问第几个成员。我们传递给get一个tuple对象,它返回指定成员的引用。get尖括号中的值必须是一个整型常量表达式。与往常一样,我们从0开始计数,意味着get<0>是第一个成员。
  • 为了使用tuple_size或tuple_element,我们需要知道一个元组对象的类型。与往常一样,确定一个对象的类型的最简单方法就是使用decltype。
  • std::tuple的一个常见用途是从一个函数返回多个值。
  • std::tuple中元素是被紧密地存储的(位于连续的内存区域),而不是链式结构。
  • std::tuple实现了多元组,这是一个编译期就确定大小的容器,可以容纳不同类型的元素。多元组类型在当前标准库中被定义为可以用任意数量参数初始化的类模板。每一模板参数确定多元组中一元素的类型。所以,多元组是一个多类型、大小固定的值的集合。

典型使用

创建和初始化

1

2

3

4

5

6

7

8

9

10

{

    std::tuple<int, double, std::string> first;    // 创建一个空的元组,需要指定元组元素的数据类型,调用各个成员的默认构造函数进行初始化。

    std::tuple<int, double, std::string> second(first);  // 拷贝构造

    std::tuple<int, char> third(10, 'a');        // 创建并初始化,使用小括号初始化

    std::tuple<int, std::string, double> fourth{42, "Test", -3.14};  // 创建并初始化,使用新的大括号初始化列表方式初始化

    std::tuple<int, char> fifth(std::make_tuple(20, 'b'));     // 移动构造,使用模板库的make_tuple

    first = std::make_tuple(1, 3.14, "tuple");       // 移动赋值

    int i_third = 3;

    std::tuple<int&> sixth(std::ref(i_third));   // 创建一个元组,元组的元素可以被引用

元组的访问和修改 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

std::get<N>()

 

{

    int n = 1;

    auto t = std::make_tuple(10, "Test", 3.14, std::ref(n), n);

    // get尖括号中的值必须是一个整型常量表达式。从0开始计数,意味着get<0>是第一个成员。

    std::cout << "The value of t is "  << "("

               << std::get<0>(t) << ", " << std::get<1>(t) << ", "

               << std::get<2>(t) << ", " << std::get<3>(t) << ", "

               << std::get<4>(t) << ")\n";

    // 由于get返回指定元素的引用,所以可用来修改指定位置的元素的值。此处因为第4个元素是引用类型,所以被引用的值也会改变

    std::get<3>(t) = 9;

    std::cout << n << std::endl;

}

元组的元素个数

使用std::tuple_size<>()

1

2

3

4

5

{

    std::tuple<char, int, long, std::string> first('A', 2, 3, "4");

    int i_count = std::tuple_size<decltype(first)>::value;  // 使用std::tuple_size计算元组个数

    std::cout << "the number of elements of a tuple:" << i_count << "\n";

}

元组的解包

std::tie() 元组包含一个或者多个元素,使用std::tie解包: 首先需要定义对应元素的变量,再使用tie。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

{ // std::tie: function template, Constructs a tuple object whose elements are references

  // to the arguments in args, in the same order

  // std::ignore: object, This object ignores any value assigned to it. It is designed to be used as an

  // argument for tie to indicate that a specific element in a tuple should be ignored.

     

    int myint;

    char mychar;

  

    std::tuple<int, float, char> mytuple;

  

    mytuple = std::make_tuple(10, 2.6, 'a');          // packing values into tuple

  

    std::tie(myint, std::ignore, mychar) = mytuple;   // unpacking tuple into variables

  

    std::cout << "myint contains: " << myint << '\n';

    std::cout << "mychar contains: " << mychar << '\n';

}

元组的元素类型获取

获取元组中某个元素的数据类型,需要用到另外一个类型: std::tuple_element。 语法: std::tuple_element<index, tuple>。

1

2

3

4

5

6

7

8

9

10

{

    std::tuple<int, std::string> third(9, std::string("ABC"));

     

    // 得到元组第1个元素的类型,用元组第一个元素的类型声明一个变量

    std::tuple_element<1, decltype(third)>::type val_1;

     

    // 获取元组的第一个元素的值

    val_1 = std::get<1>(third);

    std::cout << "val_1 = " << val_1.c_str() << "\n";

}

元组的拼接

使用 std::tuple_cat 执行拼接

1

2

3

4

5

6

7

8

9

10

11

12

13

14

{

    std::tuple<char, int, double> first('A', 1, 2.2f);

    // 组合到一起, 使用auto, 自动推导

    auto second = std::tuple_cat(first, std::make_tuple('B', std::string("-=+")));

    // 组合到一起,可以知道每一个元素的数据类型时什么 与 auto推导效果一样

    std::tuple<char, int, double, char, std::string> third = std::tuple_cat(first, std::make_tuple('B', std::string("-=+")));

    // 输出合并后的元组内容

    int index = 0;

    std::cout << index++ << " = " << std::get<0>(second) << "\n";  // 0 = A

    std::cout << index++ << " = " << std::get<1>(second) << "\n";  // 1 = 1 

    std::cout << index++ << " = " << std::get<2>(second) << "\n";  //  2 = 2.2

    std::cout << index++ << " = " << std::get<3>(second) << "\n";  // 3 = B

    std::cout << index++ << " = " << std::get<4>(second).c_str() << "\n"; // 4 = -=+

}

元组的遍历

元组没用提供operator []重载,遍历起来较为麻烦,需要为其单独提供遍历模板函数 


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/qq_41540355/article/details/122149950
相关文章
  • C++11成员函数作为回调函数的使用方式
    C++11成员函数作为回调函数使用 std::bind()被广泛地应用在新式的回调函数中。 C++11以前类的普通成员函数不能作为回调函数去注册,因为将普
  • C++11, 14, 17对tuple元素的访问介绍
    C++11, 14, 17对tuple元素的访问 std::tuple 作为可以存放任意个数,任意类型的元祖被我个人经常使用。 记得以前看侯捷谈到这个数据结构的时候
  • C++使用easyX库实现三星环绕效果流程介绍

    C++使用easyX库实现三星环绕效果流程介绍
    功能1:使用图形化的方式描述地球围绕着太阳转动,月球围绕着地球转动 功能2:在转动的过程中当用户按下1,2,3,4,5,6,7时它可以变换出7种不
  • C++时间函数整理介绍
    一、 时间概念 格林威治时间GMT(Greenwich Mean Time) 格林威治皇家天文台为了海上霸权的扩张计划,在十七世纪就开始进行天体观测。为了天
  • C++中类的六大默认成员函数的介绍

    C++中类的六大默认成员函数的介绍
    一、类的默认成员函数 二、构造函数Date(形参列表) 构造函数主要完成初始化对象,相当于C语言阶段写的Init函数。 默认构造函数:无参的构
  • C/C++实现遍历文件夹最全方法总结介绍

    C/C++实现遍历文件夹最全方法总结介绍
    一、filesystem(推荐) 在c++17中,引入了文件系统,使用起来非常方便 在VS中,可以直接在项目属性中调整: 只要是C++17即以上都可 然后头文件
  • C语言实现手写Map(数组+链表+红黑树)的代码

    C语言实现手写Map(数组+链表+红黑树)的代码
    要求 需要准备数组集合(List) 数据结构 需要准备单向链表(Linked) 数据结构 需要准备红黑树(Rbtree)数据结构 需要准备红黑树和链表适配策略
  • MySQL系列教程之使用C语言来连接数据库

    MySQL系列教程之使用C语言来连接数据库
    写在前面 知道了 Java中使用 JDBC编程 来连接数据库了,但是使用 C语言 来连接数据库却总是连接不上去~ 立即安排一波使用 C语言连接 MySQL数
  • 基于C语言实现简单学生成绩管理系统

    基于C语言实现简单学生成绩管理系统
    一、系统主要功能 1、密码登录 2、输入数据 3、查询成绩 4、修改成绩 5、输出所有学生成绩 6、退出系统 二、代码实现 1 2 3 4 5 6 7 8 9 10 11
  • C语言实现共享单车管理系统

    C语言实现共享单车管理系统
    1.功能模块图; 2.各个模块详细的功能描述。 1.登陆:登陆分为用户登陆,管理员登陆以及维修员登录,登陆后不同的用户所执行的操作
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计