Namespaces
Variants

std::tuple<Types...>:: tuple

From cppreference.net
Utilities library
定义于头文件 <tuple>
constexpr tuple ( ) ;
(1) (C++11 起)
(条件性 explicit)
tuple ( const Types & ... args ) ;
(2) (C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)
template < class ... UTypes >
tuple ( UTypes && ... args ) ;
(3) (C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)
template < class ... UTypes >
constexpr tuple ( tuple < UTypes... > & other ) ;
(4) (C++23 起)
(条件性 explicit)
template < class ... UTypes >
tuple ( const tuple < UTypes... > & other ) ;
(5) (C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)
template < class ... UTypes >
tuple ( tuple < UTypes... > && other ) ;
(6) (C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)
template < class ... UTypes >
constexpr tuple ( const tuple < UTypes... > && other ) ;
(7) (C++23 起)
(条件性 explicit)
template < class U1, class U2 >
constexpr tuple ( std:: pair < U1, U2 > & p ) ;
(8) (C++23 起)
(条件性 explicit)
template < class U1, class U2 >
tuple ( const std:: pair < U1, U2 > & p ) ;
(9) (C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)
template < class U1, class U2 >
tuple ( std:: pair < U1, U2 > && p ) ;
(10) (C++11 起)
(C++14 起为 constexpr)
(条件性 explicit)
template < class U1, class U2 >
constexpr tuple ( const std:: pair < U1, U2 > && p ) ;
(11) (C++23 起)
(条件性 explicit)
template < tuple - like UTuple >
constexpr tuple ( UTuple && u ) ;
(12) (C++23 起)
(条件性 explicit)
tuple ( const tuple & other ) = default ;
(13) (C++11 起)
tuple ( tuple && other ) = default ;
(14) (C++11 起)
分配器扩展构造函数
template < class Alloc >
tuple ( std:: allocator_arg_t , const Alloc & a ) ;
(15) (C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template < class Alloc >

tuple ( std:: allocator_arg_t , const Alloc & a,

const Types & ... args ) ;
(16) (C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template < class Alloc, class ... UTypes >

tuple ( std:: allocator_arg_t , const Alloc & a,

UTypes && ... args ) ;
(17) (C++11 起)
(C++20 起为 constexpr)
(条件性 explicit)
template < <span class="kw1

构造一个新的元组。

在以下描述中,令

  • i 在范围 [ 0 , sizeof... ( Types ) ) 内按顺序取值,
  • Ti 表示 Types 中的第 i 个类型,且
  • Ui 表示名为 UTypes 的模板参数包中的第 i 个类型,

其中索引从零开始。

1) 默认构造函数。若存在元素则对所有元素进行 值初始化 。当 sizeof... ( Types ) == 0 时,该默认构造函数是平凡的。
  • 仅当对所有 i 满足 std:: is_default_constructible < Ti > :: value true 时,此重载才会参与重载决议。
  • 当且仅当至少存在一个 i 使得 Ti 无法从 { } 进行复制列表初始化时,该构造函数为 explicit
2) 直接构造函数。使用对应参数初始化元组的每个元素。
  • 仅当满足 sizeof... ( Types ) >= 1 且对所有 i 满足 std:: is_copy_constructible < Ti > :: value true 时,此重载才会参与重载决议。
  • 当且仅当至少存在一个 i 使得 std:: is_convertible < const Ti & , Ti > :: value false 时,此构造函数为 explicit
3) 转换构造函数。使用 std:: forward < UTypes > ( args ) 中的对应值初始化元组的每个元素。
  • 此重载仅在以下条件满足时参与重载决议:
  • 当且仅当对至少一个 i std:: is_convertible < Ui, Ti > :: value false 时,该构造函数为 explicit
(C++23 起)
4-7) 转换构造函数。使用 other 的对应元素初始化 tuple 的每个元素。

形式化地,令 FWD ( other ) std:: forward < decltype ( other ) > ( other ) ,对于所有 i ,使用 std :: get < i > ( FWD ( other ) ) 初始化 tuple 的第 i 个元素。

  • 此重载仅当满足以下所有条件时才参与重载决议:
  • 当且仅当对至少一个 i std:: is_convertible_v < decltype ( std :: get < i > ( FWD ( other ) ) ) , Ti > false 时,这些构造函数为 explicit
  • 如果任何引用类型元素的初始化会将其绑定到临时对象,则这些构造函数被定义为被删除的。
(since C++23)
8-11) 对构造函数。构造一个包含两个元素的元组,其中每个元素从 p 的对应元素构造。

形式化地,令 FWD ( p ) std:: forward < decltype ( p ) > ( p ) ,使用 std :: get < 0 > ( FWD ( p ) ) 初始化第一个元素,并使用 std :: get < 1 > ( FWD ( p ) ) 初始化第二个元素。

  • 如果任何引用元素的初始化会将其绑定到临时对象,则这些构造函数被定义为删除的。
(since C++23)
12) tuple-like 构造函数。构造一个元组,其中每个元素从 u 的对应元素构造。

形式上,对于所有 i ,用 std :: get < i > ( std:: forward < UTuple > ( u ) ) 初始化元组的第 i 个元素。

13) 隐式定义的复制构造函数。使用 other 的对应元素初始化元组的每个元素。
  • 若该构造函数执行的每个操作均为 constexpr ,则此构造函数为 constexpr 。对于空元组 std:: tuple <> ,该构造函数为 constexpr
  • 对所有 i std:: is_copy_constructible < Ti > :: value 必须为 true ,否则 行为未定义 (C++20 前) 程序非良构 (C++20 起)
14) 隐式定义的移动构造函数。对于所有 i ,使用 std:: forward < Ui > ( std :: get < i > ( other ) ) 初始化元组的第 i 个元素。
  • 若该构造函数执行的所有操作均为 constexpr ,则此构造函数为 constexpr 。对于空元组 std:: tuple <> ,该构造函数为 constexpr
  • 对所有 i std:: is_move_constructible < Ti > :: value 必须为 true ,否则 行为未定义 (C++20 前) 此重载不参与重载决议 (C++20 起)
15-28) (1-14) 相同,区别在于每个元素通过 使用分配器构造 创建,即分配器对象 a 作为额外参数传递给每个元素的构造函数,前提是该元素的 std:: uses_allocator < Ui, Alloc > :: value true

目录

参数

args - 用于初始化元组各元素的值
other - 用于初始化元组各元素的值构成的元组
p - 用于初始化二元组两个元素的数值对
u - 用于初始化元组各元素的值构成的 tuple-like 对象
a - 用于分配器构造的分配器

注释

条件性显式构造函数使得在复制初始化上下文中使用列表初始化语法构造元组成为可能:

std::tuple<int, int> foo_tuple() 
{
    // return {1, -1};             // N4387 标准前的错误用法
    return std::make_tuple(1, -1); // 始终有效
}

注意,如果列表中的某些元素无法隐式转换为目标元组的对应元素,则构造函数将变为显式:

using namespace std::chrono;
void launch_rocket_at(std::tuple<hours, minutes, seconds>);
launch_rocket_at({hours(1), minutes(2), seconds(3)}); // 正确
launch_rocket_at({1, 2, 3}); // 错误:int 不能隐式转换为 duration 类型
launch_rocket_at(std::tuple<hours, minutes, seconds>{1, 2, 3}); // 正确

示例

#include <iomanip>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <tuple>
#include <type_traits>
#include <vector>
// 辅助函数:将向量打印到流
template<class Os, class T>
Os& operator<<(Os& os, std::vector<T> const& v)
{
    os << '{';
    for (auto i{v.size()}; const T& e : v)
        os << e << (--i ? "," : "");
    return os << '}';
}
template<class T>
void print_single(T const& v)
{
    if constexpr (std::is_same_v<T, std::decay_t<std::string>>)
        std::cout << std::quoted(v);
    else if constexpr (std::is_same_v<std::decay_t<T>, char>)
        std::cout << "'" << v << "'";
    else
        std::cout << v;
}
// 辅助函数:打印任意大小的元组
template<class Tuple, std::size_t N>
struct TuplePrinter
{
    static void print(const Tuple& t)
    {
        TuplePrinter<Tuple, N - 1>::print(t);
        std::cout << ", ";
        print_single(std::get<N - 1>(t));
    }
};
template<class Tuple>
struct TuplePrinter<Tuple, 1>
{
    static void print(const Tuple& t)
    {
        print_single(std::get<0>(t));
    }
};
template<class... Args>
void print(std::string_view message, const std::tuple<Args...>& t)
{
    std::cout << message << " (";
    TuplePrinter<decltype(t), sizeof...(Args)>::print(t);
    std::cout << ")\n";
}
// 辅助函数结束
int main()
{
    std::tuple<int, std::string, double> t1;
    print("值初始化,t1:", t1);
    std::tuple<int, std::string, double> t2{42, "Test", -3.14};
    print("使用值初始化,t2:", t2);
    std::tuple<char, std::string, int> t3{t2};
    print("隐式转换,t3:", t3);
    std::tuple<int, double> t4{std::make_pair(42, 3.14)};
    print("从pair构造,t4:", t4);
    // 给定具有单参数构造函数的分配器 my_alloc
    // my_alloc(int);使用 my_alloc(1) 在vector中分配5个整数
    using my_alloc = std::allocator<int>;
    std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}};
    // 使用 my_alloc(2) 在元组中的vector内分配5个整数
    std::tuple<int,

缺陷报告

下列行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。

缺陷报告 应用于 发布时的行为 正确行为
LWG 2510 C++11 默认构造函数为隐式声明 改为条件性显式
LWG 3121 C++11 单元素元组构造函数可能递归检查约束;
allocator_arg_t 参数引发歧义
进一步约束
构造函数
LWG 3158 C++11 对应默认构造函数的
分配器使用构造函数为隐式声明
改为条件性显式
LWG 3211 C++11 tuple<> 的默认构造函数
是否为平凡类型未作规定
要求必须为平凡类型
LWG 4045 C++23 tuple-like 构造函数可能产生悬垂引用 定义为已删除
N4387 C++11 部分构造函数为显式声明,阻碍了有用行为 多数构造函数改为
条件性显式

参见

将一个 tuple 的内容赋值给另一个
(公开成员函数)
(C++11)
根据参数类型创建对应类型的 tuple 对象
(函数模板)
(C++11)
创建左值引用组成的 tuple 或将 tuple 解包为独立对象
(函数模板)
创建由 转发引用 构成的 tuple
(函数模板)
构造新的 pair
( std::pair<T1,T2> 的公开成员函数)