「这是我参与11月更文挑战的第 7 天,活动详情查看:2021最后一次更文挑战」。
参加该活动的第 14 篇文章
正文
tuple 是一组有序的值 (an ordered set of values) 。在关系数据库中,某个表格的一行也可以称为 tuple ;而在编程语言中,tuple 也可以用来储存从数据库表格中检索出来的一行。
pair 和 tuple 的代码对比示例
对 C++ 编程来说,pair 应该不陌生。tuple 是一个固定大小的不同类型值的集合,而 tuple 可视为 pair 的一般化,。比较麻烦的是用 tuple 时必须使用 std::get
来取得 tuple 內的值。
#include <iostream>
#include <string>
#include <tuple>
/// @note
void UsePair() {
std::pair<int, std::string> p1 = { 1, "kenny" };
std::pair<float, char> p2 = std::make_pair(15.6f, 'b');
std::cout << p1.first << ", " << p1.second << std::endl;
std::cout << p2.first << ", " << p2.second << std::endl;
}
/// @note
/// 使用 make_tuple 构造 tuple
/// 使用 get 获取指定 tuple 元素
void UseTuple() {
std::tuple<int, double, std::string> t1(1, 15.4, "James");
std::cout << std::get<0>(t1) << std::endl;
std::cout << std::get<1>(t1) << std::endl;
std::cout << std::get<2>(t1) << std::endl;
/// @note 构造一个 tuple
std::tuple<int, float, char> t2 = std::make_tuple(2, 35.2f, 'a');
std::cout << std::get<0>(t2) << std::endl;
std::cout << std::get<1>(t2) << std::endl;
std::cout << std::get<2>(t2) << std::endl;
}
void main() {
UsePair();
UseTuple();
}
使用 std::tie 获取 tuple 的值
使用 std::tie
,它会创建一个元组的左值引用。如下例所示,通过 tie 解包后,mytuple
中三个值会自动赋值给 tie 中的前后两个变量(我们如果只想解某个位置的值时,可以用 std::ignore
占位符来表示不解某个位置的值)。
std::tuple<int, float, char> mytuple;
mytuple = std::make_tuple(10, 2.6, 'a'); // packing values into tuple
int myint;
char mychar;
std::tie(myint, std::ignore, mychar) = mytuple; // unpacking tuple into variables
std::cout << "myint contains: " << myint << '\n';
std::cout << "mychar contains: " << mychar << '\n';
使用 std::forward_as_tuple 创建 tuple 的方法
使用 std::forward_as_tuple
创建的是右值引用的 tuple
示例如下
std::map<int, std::string> m;
m.emplace(std::piecewise_construct,
std::forward_as_tuple(10),
std::forward_as_tuple(20, 'a'));
以上代码实际上创建了一个类似于 std::tuple<int&&, std::string&&>
类型的 tuple
。
连接多个 tuple
示例如下
int main()
{
std::tuple<int, std::string, float> t1(10, "Test",
3.14);
int n = 7;
auto t2 = std::tuple_cat(t1, std::make_pair("Foo", "bar"), t1, std::tie(n));
n = 10;
print(t2);
}
输出结果为
(10, Test, 3.14, Foo, bar, 10, Test, 3.14, 10)
像初始化 vector 一样初始化 tuple
以下代码使用于 C++ 14 [VS2015/VS2017/VS2019 均测试通过
]
在 C++ 11 中,我们可以通过 std::vector v = {1, 2, 3, 4};
方便地初始化 vector 。但是 tuple 却必须要到 C++ 14 以上才会支持这种初始化的方式。所以在低于 C++ 14 的编译器上上面的示例会产生编译错误。
#include <iostream>
#include <tuple>
void UseTuple() {
/// @note 需要支持 C++ 14 以上才能编译通过
std::tuple<int, float, char> t3 = { 2, 35.2f, 'a' };
std::cout << std::get<0>(t3) << std::endl;
std::cout << std::get<1>(t3) << std::endl;
std::cout << std::get<2>(t3) << std::endl;
}
/// @note 返回 2 个或以上的返回值
std::tuple<int, int> ReturnTuple() {
/// @note 需要支持 C++ 14 以上才能编译通过
return { 5, 6 };
/// @note 如果是 C++ 11, 我们就只能使用以下形式
//return std::make_tuple(5, 6);
}
void main() {
UseTuple();
ReturnTuple();
}
利用 tuple 获取结构体内部的数据类型
结构体定义了一个 Get 方法来返回其字段的基本信息
struct A
{
int x;
double y;
auto Get()->decltype(std::make_tuple(x,y))
{
//const type_info& nInfo = typeid(decltype(std::make_tuple(x, y)));
//std::cout << nInfo.name()<< std::endl;
return std::make_tuple(x,y);
}
};
引申
高级的 tuple 使用方法可以参考 C++11 / C++14 中 tuple 的高级使用
更多 tuple 相关操作可以参考 cppreference.com