# std::tuple_element

< cpp‎ | utility

定义于头文件 `<tuple>` |  |
定义于头文件 `<array>` |  |
定义于头文件 `<utility>` |  |
定义于头文件 `<ranges>` |  | (C++20 起)
template< std::size_t I, class T > struct tuple_element; // 不定义 | (1) | (C++11 起)
template< std::size_t I, class T > struct tuple_element< I, const T > { using type = typename std::add_const<typename std::tuple_element<I, T>::type>::type; }; | (2) | (C++11 起)
template< std::size_t I, class T > struct tuple_element< I, volatile T > { using type = typename std::add_volatile<typename std::tuple_element<I, T>::type>::type; }; | (3) | (C++11 起) (C++20 中弃用)
template< std::size_t I, class T > struct tuple_element< I, const volatile T > { using type = typename std::add_cv<typename std::tuple_element<I, T>::type>::type; }; | (4) | (C++11 起) (C++20 中弃用)

提供对元组式类型的元素类型的编译时下标访问。

1) 不定义主模板。要求显式（全）或部分特化以令类型为元组式。
2-4) 对 cv 限定类型的特化默认简单地添加对应的 cv 限定符。

`std::tuple_element` 与核心语言交互：它能在元组式情况下提供结构化绑定支持。 | (C++17 起)

### 特化

标准库对标准库类型提供下列特化：

std::tuple_element<std::tuple> (C++11) | 获得指定元素的类型 (类模板特化)
std::tuple_element<std::pair> (C++11) | 获得 `pair` 中元素的类型 (类模板特化)
std::tuple_element<std::array> (C++11) | 获得 `array` 元素的类型 (类模板特化)
std::tuple_element<std::ranges::subrange> (C++20) | 获得 std::ranges::subrange 的迭代器或哨位的类型 (类模板特化)

用户可以对程序定义类型特化 `std::tuple_size` 以令它们为元组式。

在 `get` 函数返回引用成员或到子对象的引用的通常情况下，只需要定制对 cv 无限定类型的特化。

### 成员类型

成员类型 | 定义
type | 对标准特化，为元组式类型 `T` 的第 `I` 个元素，其中 `I` 在 [0, std::tuple_size<T>::value) 中

### 辅助类型

定义于头文件 `<tuple>` |  |
template <std::size_t I, class T> using tuple_element_t = typename tuple_element<I, T>::type; |  | (C++14 起)

### 示例

    #include <array>
    #include <cstddef>
    #include <iostream>
    #include <ranges>
    #include <tuple>
    #include <type_traits>
    #include <utility>

    template <typename T1, typename T2, typename T3>
        struct Triple { T1 t1; T2 t2; T3 t3; };

    // A specialization of std::tuple_element for program-defined type Triple:
    template <std::size_t I, typename T1, typename T2, typename T3>
        struct std::tuple_element<I, Triple<T1, T2, T3>> { static_assert(I < 4); };
    template <typename T1, typename T2, typename T3>
        struct std::tuple_element<0, Triple<T1, T2, T3>> { using type = T1; };
    template <typename T1, typename T2, typename T3>
        struct std::tuple_element<1, Triple<T1, T2, T3>> { using type = T2; };
    template <typename T1, typename T2, typename T3>
        struct std::tuple_element<2, Triple<T1, T2, T3>> { using type = T3; };

    template <typename... Args> struct TripleTypes {
        static_assert(3 == sizeof...(Args), "Expected exactly 3 type names!");
        template <std::size_t N>
            using type = typename std::tuple_element_t<N, Triple<Args...>>;
    };

    int main()
    {
        TripleTypes<char, int, float>::type<1> i{42};
        std::cout << i << '\n';

        using Tri = Triple<int, char, short>; //< Program-defined type
        static_assert(std::is_same_v<std::tuple_element_t<0, Tri>, int> &&
                      std::is_same_v<std::tuple_element_t<1, Tri>, char> &&
                      std::is_same_v<std::tuple_element_t<2, Tri>, short>);

        using Tuple = std::tuple<int, char, short>;
        static_assert(std::is_same_v<std::tuple_element_t<0, Tuple>, int> &&
                      std::is_same_v<std::tuple_element_t<1, Tuple>, char> &&
                      std::is_same_v<std::tuple_element_t<2, Tuple>, short>);

        using Array3 = std::array<int, 3>;
        static_assert(std::is_same_v<std::tuple_element_t<0, Array3>, int> &&
                      std::is_same_v<std::tuple_element_t<1, Array3>, int> &&
                      std::is_same_v<std::tuple_element_t<2, Array3>, int>);

        using Pair = std::pair<Tuple, Tri>;
        static_assert(std::is_same_v<std::tuple_element_t<0, Pair>, Tuple> &&
                      std::is_same_v<std::tuple_element_t<1, Pair>, Tri>);

        using Sub = std::ranges::subrange<int*, int*>;
        static_assert(std::is_same_v<std::tuple_element_t<0, Sub>, int*> &&
                      std::is_same_v<std::tuple_element_t<1, Sub>, int*>);
    }

输出：

    42

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 2212 | C++11 | 未在某些头文件中要求对 cv 类型的特化，这导致歧义 | 已要求

### 参阅

结构化绑定 (C++17) | 绑定指定的名字到初始化器的子对象或元组元素
tuple_size (C++11) | 获得元组式类型的元素数 (类模板)
tuple_cat | 通过连接任意数量的元组来创建一个`tuple` (函数模板)