c++11中的std::tuple元组和std::tie

功能简介

std::tuple是c++11提供的新模板类,在很多流行语言都有对应的实现,一般翻译为元组。使用它可以把多个不同类型的变量组合成一个对象。

简单示例

以下是std::tuple的简单示例(来源:https://en.cppreference.com/w/cpp/utility/tuple)

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
#include <tuple>
#include <iostream>
#include <string>
#include <stdexcept>

std::tuple<double, char, std::string> get_student(int id)
{
// C++11构建tuple的写法
if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");

// C++17提供了更方便的构建tuple的写法
//if (id == 0) return { 3.8, 'A', "Lisa Simpson" };

if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
throw std::invalid_argument("id");
}

int main()
{
auto student0 = get_student(0);
// 通过下标位置获取tuple中对应的元素
std::cout << "ID: 0, "
<< "GPA: " << std::get<0>(student0) << ", "
<< "grade: " << std::get<1>(student0) << ", "
<< "name: " << std::get<2>(student0) << '\n';

// 通过tie将tuple中的元素解构至多个变量中
double gpa1;
char grade1;
std::string name1;
std::tie(gpa1, grade1, name1) = get_student(1);
std::cout << "ID: 1, "
<< "GPA: " << gpa1 << ", "
<< "grade: " << grade1 << ", "
<< "name: " << name1 << '\n';

// C++17提供了更方便的解构写法
//auto [ gpa2, grade2, name2 ] = get_student(2);
//std::cout << "ID: 2, "
// << "GPA: " << gpa2 << ", "
// << "grade: " << grade2 << ", "
// << "name: " << name2 << '\n';
}

和struct比较

先看例子,再做比较

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
struct student {
double gpa;
char grade;
std::string name;
};

student get_student(int id) {
if (id == 0) {
student s;
s.gpa = 3.8;
s.grade = 'A';
s.name = "Lisa Simpson";
return s;
}
// ...省略构建其余id的重复代码,只做简单演示
}

int main {
auto student0 = get_student(0);

std::cout << "ID: 0, "
<< "GPA: " << student0.gpa << ", "
<< "grade: " << student0.grade << ", "
<< "name: " << student0.name << '\n';
// ...省略获取其余id的重复代码,只做简单演示
}

相比较于std::tuple,struct需要定义结构体这个复合类型。

如果单说以上所举例的这个场景,个人觉得struct的写法表意更清晰些。
原因是函数get_student所返回的gpa、grade、name三个元素变量在含义上本身是非常紧密的。
假设我们除了这个函数,还有其他地方需要同时使用这三个变量,比如update_student或print_student等,那么struct的写法将更合适些。

多说一句,作为开发,我们要保持学习新知识的习惯。但是不能有了新锤子,就看哪都是钉子。为了用新技术而用。
而应该带着新锤子,观察和思考哪有合适钉子,再合理运用。

和std::pair比较

先看例子,再做比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
std::pair<double, std::pair<char, std::string> > get_student(int id) {
if (id == 0) {
return std::make_pair(3.8, std::make_pair('A', "Lisa Simpson"));
}
// ...省略构建其余id的重复代码,只做简单演示
}

int main() {
auto student0 = get_student(0);
std::cout << "ID: 0, "
<< "GPA: " << student0.first << ", "
<< "grade: " << student0.second.first << ", "
<< "name: " << student0.second.second << '\n';
// ...省略获取其余id的重复代码,只做简单演示
return 0;
}

相比较于std::tuple,std::pair如果想要支持多于2个的变量,需要多层嵌套或结合struct使用。

std::tie的其他用法

std::tie除了第一个例子中演示的用于解构std::tuple中的元素,还可以用来将多个变量构造成std::tuple,从而做大小比较。例如 https://en.cppreference.com/w/cpp/utility/tuple/tie 中演示的例子。这种写法更modern些~

结尾

参考链接

原文链接: https://pengrl.com/p/58825/
原文出处: yoko blog (https://pengrl.com)
原文作者: yoko (https://github.com/q191201771)
版权声明: 本文欢迎任何形式转载,转载时完整保留本声明信息(包含原文链接、原文出处、原文作者、版权声明)即可。本文后续所有修改都会第一时间在原始地址更新。

fccxy

0%