Skip to main content
Version: 1.0

tuple

std::tuple 是 C++11 引入的固定大小异构容器,用于将多个不同类型的值组合成一个对象。它可以容纳任意数量、任意类型的元素,是 std::pair 的扩展。

std::pair 的区别:

  1. pair 只能存两个元素,tuple 可以存任意数量(通过模板参数)。
  2. tuple 适合返回多个值的函数、多值关联等场景。
  3. 访问方式既可以通过索引(编译时 std::get<N>),也可以通过类型(仅当该类型唯一时)。

头文件与基本特征

#include <tuple>

主要特征:

特征说明
元素类型任意类型(异构)
大小固定,编译时确定
存储方式值语义(非引用)
拷贝语义完整拷贝
移动语义支持移动构造和移动赋值

基本用法

使用 std::make_tuple 创建:

#include <iostream>
#include <tuple>
#include <string>

int main() {
auto t = std::make_tuple(42, std::string("hello"), 3.14);

std::cout << std::get<0>(t) << '\n'; // 42
std::cout << std::get<1>(t) << '\n'; // hello
std::cout << std::get<2>(t) << '\n'; // 3.14
return 0;
}

也可以通过构造函数直接创建:

std::tuple<int, std::string, double> t(10, "world", 2.718);

交互演示(MDX + React)

下面这个面板用于演示 make_tuplestd::get<N>std::get<T>std::tie 以及 std::tuple_cat 的典型行为:

std::tuple 操作演示

通过交互操作体验 tuple 的创建、元素访问、tuple_cat 等核心用法。

MDX + React
#0int42
#1stringhello
#2double3.14
元素数量3
类型tuple<int, string, double>

创建与构造

元素访问

增删元素

最近操作

  • 初始化: std::tuple<int, string, double>

元素访问

std::get<N>

通过编译时索引访问元素:

#include <tuple>

int main() {
auto t = std::make_tuple(100, 200, 300);

int a = std::get<0>(t); // 100
int b = std::get<1>(t); // 200
int c = std::get<2>(t); // 300

return 0;
}

索引必须是编译时常量,越界会导致编译错误。

std::get<T>

当 tuple 中某类型唯一时,可以按类型访问:

#include <tuple>
#include <string>

int main() {
auto t = std::make_tuple(42, std::string("hi"));

int n = std::get<int>(t); // 正确:int 是唯一的
std::string s = std::get<std::string>(t); // 正确:string 是唯一的

return 0;
}

如果有多个相同类型,编译会报错。

std::tie

std::tie 用于解包 tuple 到变量:

#include <tuple>
#include <string>
#include <iostream>

int main() {
auto t = std::make_tuple(1, 2, std::string("hello"));

int a, b;
std::string c;
std::tie(a, b, c) = t;

std::cout << a << ' ' << b << ' ' << c << '\n';
return 0;
}

常用场景:函数返回多个值并赋值给独立变量。

创建与赋值

std::make_tuple

自动推断元素类型:

auto t = std::make_tuple(10, 3.14, std::string("test"));

std::tuple_cat

合并多个 tuple:

#include <tuple>
#include <iostream>

int main() {
auto t1 = std::make_tuple(1, 2);
auto t2 = std::make_tuple(3, 4.0);

auto combined = std::tuple_cat(t1, t2);
// combined 是 std::tuple<int, int, int, double>

return 0;
}

pair 与 tuple 互相转换

pair 本身就是一种特殊的 tuple,可以直接赋值:

#include <tuple>
#include <utility>
#include <iostream>

int main() {
std::pair<int, std::string> p(42, "hi");

std::tuple<int, std::string> t = p;
std::pair<int, std::string> p2 = t;

return 0;
}

常用辅助函数

函数作用
std::make_tuple()创建 tuple,自动推断类型
std::get<N>(t)按索引访问元素
std::get<T>(t)按类型访问元素(类型需唯一)
std::tie()解包 tuple 到变量
std::tuple_cat()拼接多个 tuple
std::tuple_size<...>编译时获取元素个数
std::tuple_element<N, ...>获取第 N 个元素的类型
operator== / operator<逐元素比较(C++20 起支持相等比较)
std::swap(t1, t2)交换两个 tuple

tuple_sizetuple_element

#include <tuple>
#include <iostream>

int main() {
using T = std::tuple<int, double, std::string>;

constexpr std::size_t sz = std::tuple_size<T>::value; // 3

using FirstType = std::tuple_element_t<0, T>; // int

return 0;
}

tuple 作为函数返回值

tuple 适合从函数返回多个不同类型的值:

#include <tuple>
#include <string>

std::tuple<int, double, std::string> getRecord() {
return {42, 3.14, std::string("data")};
}

int main() {
auto [id, score, name] = getRecord(); // C++17 结构化绑定
return 0;
}

C++17 的结构化绑定让 tuple 的使用更加自然:

auto [a, b, c] = std::make_tuple(1, 2.5, std::string("x"));

常见用法示例

多值返回

#include <tuple>
#include <string>

std::tuple<bool, int, std::string> tryParse(const std::string& s) {
// 模拟解析逻辑
try {
int value = std::stoi(s);
return {true, value, ""};
} catch (...) {
return {false, 0, "parse error"};
}
}

int main() {
auto [ok, val, err] = tryParse("123");
return 0;
}

字典与多值映射

#include <tuple>
#include <unordered_map>
#include <string>

int main() {
std::unordered_map<std::string, std::tuple<int, double, std::string>> db;

db["alice"] = std::make_tuple(95, 1.65, "Beijing");
db["bob"] = std::make_tuple(88, 1.80, "Shanghai");

auto& [score, height, city] = db["alice"];
return 0;
}

使用注意

  1. std::get<N> 的索引必须是编译时常量。
  2. std::get<T> 要求该类型在 tuple 中唯一。
  3. tuple 本身不提供运行时动态添加/删除元素的能力,大小在编译时固定。
  4. 元素按值存储,深拷贝适用于所有非指针成员。
  5. 大量异构元素时,考虑是否有更清晰的专用结构体替代。
  6. C++17 结构化绑定 auto [a, b, c] = t; 是最推荐的解包方式。

小结

std::tuple 是 C++11 处理异构数据集合的核心工具。它弥补了 std::pair 只支持两个元素的限制,配合 std::get<N>std::tiestd::tuple_cat 等工具以及 C++17 结构化绑定,可以优雅地解决多值返回、批量数据传输等常见场景。合理使用 tuple 让代码更简洁,同时注意不要滥用导致类型混乱。