std::tuple类型

1. 元组简介

std::tuple是类似std::pair的模板。每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同std::tuple类型的成员类型也不相同,但一个std::tuple可以有任意数量的成员。每个确定的std::tuple类型的成员数目是固定的,但一个std::tuple类型的成员数目可以与另一个std::tuple类型不同。

但我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,std::tuple是非常有用的。我们可以将std::tuple看作一个”快速而随意”的数据结构。

当我们定义一个std::tuple时,需要指出每个成员的类型。当我们创建一个std::tuple对象时,可以使用std::tuple的默认构造函数,它会对每个成员进行值初始化;也可以为每个成员提供一个初始值,此时的构造函数是explicit的,因此必须使用直接初始化方法。类似std::make_pair函数,标准库定义了std::make_tuple函数,我们还可以使用它来生成std::tuple对象。类似std::make_pair,std::make_tuple函数使用初始值的类型来推断std::tuple的类型。

一个std::tuple类型的成员数目是没有限制的,因此,std::tuple的成员都是未命名的。要访问一个tstd::uple的成员,就要使用一个名为std::get的标准库函数模板。为了使用std::get,我们必须指定一个显式模板实参,它指出我们想要访问第几个成员。我们传递给std::get一个std::tuple对象,它返回指定成员的引用。std::get尖括号中的值必须是一个整型常量表达式。与往常一样,我们从0开始计数,意味着std::get<0>是第一个成员。

为了使用tuple_size或tuple_element,我们需要知道一个std::tuple对象的类型。与往常一样,确定一个对象的类型的最简单方法就是使用decltype。

std::tuple的关系和相等运算符的行为类似容器的对应操作。这些运算符逐对比较左侧tuple和右侧tuple的成员。只有两个std::tuple具有相同数量的成员时,我们才可以比较它们。而且,为了使用std::tuple的相等或不等运算符,对每对成员使用==运算符必须都是合法的;为了使用关系运算符,对每对成员使用<必须都是合法的。由于std::tuple定义了<和==运算符,我们可以将tuple序列传递给算法,并且可以在无序容器中将std::tuple作为关键字类型。

std::tuple的一个常见用途是从一个函数返回多个值。

std::tuple是一个模板,允许我们将多个不同类型的成员捆绑成单一对象。每个tuple包含指定数量的成员,但对一个给定的tuple类型,标准库并未限制我们可以定义的成员数量上限。

std::tuple中元素是被紧密地存储的(位于连续的内存区域),而不是链式结构。

std::tuple实现了多元组,这是一个编译期就确定大小的容器,可以容纳不同类型的元素。多元组类型在当前标准库中被定义为可以用任意数量参数初始化的类模板。每一模板参数确定多元组中一元素的类型。所以,多元组是一个多类型、大小固定的值的集合。

 2. 官方文档介绍

(C++11 起) 

类模板 std::tuple 是固定大小的异类值汇集。它是 std::pair 的推广。

3. 配合使用函数

3.1. std::make_tuple

std::tuple<int, int> foo_tuple() 
{
  return {1, -1};  // N4387 前错误
  return std::tuple<int, int>{1, -1};  // 始终有效, tuple可以使用初始化列表进行赋值。
  return std::make_tuple(1, -1); // 始终有效
}

3.2. std::get

#include <iostream>
#include <string>
#include <tuple>
 
int main()
{
    auto t = std::make_tuple(1, "Foo", 3.14);
    // 基于下标的访问
    std::cout << "(" << std::get<0>(t) << ", " << std::get<1>(t)
              << ", " << std::get<2>(t) << ")\n";
    // 基于类型的访问( C++14 起)
    std::cout << "(" << std::get<int>(t) << ", " << std::get<const char*>(t)
              << ", " << std::get<double>(t) << ")\n";
    // 注意: std::tie 和结构化绑定亦可用于分解 tuple
}

3.3. std::tie

#include <tuple>
#include <iostream>
#include <string>
#include <stdexcept>
 
std::tuple<double, char, std::string> get_student(int id)
{
    if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson"); //生成一个std::tuple
    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);
    std::cout << "ID: 0, "
              << "GPA: " << std::get<0>(student0) << ", " //std::get用于取出tuple中的某个值
              << "grade: " << std::get<1>(student0) << ", "
              << "name: " << std::get<2>(student0) << '\n';
 
    double gpa1;
    char grade1;
    std::string name1;
    std::tie(gpa1, grade1, name1) = get_student(1);//std::tie的用法!!std::tie会将变量的引用整合成一个tuple,从而实现批量赋值
    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';
}

3.4. std::ignore

使用std::ignore忽略某些tuple中的某些返回值

double gpa1;
std::string name1;
std::tie(gpa1, ignore, name1) = get_student(1);

3.4. std::forward_as_tuple

Constructs a tuple of references to the arguments in args suitable for forwarding as an argument to a function. The tuple has rvalue reference data members when rvalues are used as arguments, and otherwise has lvalue reference data members.

#include <iostream>
#include <map>
#include <tuple>
#include <string>
 
int main()
{
    std::map<int, std::string> m;
 
    m.emplace(std::piecewise_construct,
              std::forward_as_tuple(10),
              std::forward_as_tuple(20, 'a'));
    std::cout << "m[10] = " << m[10] << '\n';
 
    // The following is an error: it produces a
    // std::tuple<int&&, char&&> holding two dangling references.
    //
    // auto t = std::forward_as_tuple(20, 'a');
    // m.emplace(std::piecewise_construct, std::forward_as_tuple(10), t);
}

Output

m[10] = aaaaaaaaaaaaaaaaaaaa
void print_pack(std::tuple<std::string&&, int&&> pack)
{
	std::cout << std::get<0>(pack) << ", " << std::get<1>(pack) << '\n';
}

print_pack(std::forward_as_tuple(str + " Smith", 25));
print_pack(std::forward_as_tuple(str + " Daniels", 22));

参考文献

C++STL之tuple类型_tie函数_get函数_Peace-CSDN博客

std::forward_as_tuple - cppreference.com

C++11中std::tuple的使用_网络资源是无限的-CSDN博客

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值