std::tuple_element - cppreference.com (original) (raw)

Defined in header
Defined in header
Defined in header
Defined in header (since C++20)
Defined in header (since C++26)
template< std::size_t I, class T > struct tuple_element; // not defined (1) (since 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) (since 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) (since C++11) (deprecated in 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) (since C++11) (deprecated in C++20)

Provides compile-time indexed access to the types of the elements of a tuple-like type.

  1. The primary template is not defined. An explicit (full) or partial specialization is required to make a type tuple-like.

2-4) Specializations for cv-qualified types simply add corresponding cv-qualifiers by default.

std::tuple_element interacts with the core language: it can provide structured binding support in the tuple-like case. (since C++17)

Contents

[edit] Specializations

The standard library provides following specializations for standard library types:

Users may specialize std::tuple_element for program-defined types to make them tuple-like.

In normal cases where the get functions returns reference members or reference to subobjects, only specializations for cv-unqualified types are needed to be customized.

[edit] Member types

Member type Definition
type for a standard specialization, the type of Ith element of the tuple-like type T, where I is in [​0​, std::tuple_size<T>::value)

[edit] Helper types

| | | | | ------------------------------------------------------------------------------------------------------------------------------- | | ------------- | | template< std::size_t I, class T > using tuple_element_t = typename tuple_element<I, T>::type; | | (since C++14) |

[edit] Notes

Feature-test macro Value Std Feature
__cpp_lib_tuple_element_t 201402L (C++14) std::tuple_element_t

[edit] Example

#include #include #include #include #include #include #include   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(false, "Invalid index"); }; 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*>); }

Output:

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 2212 C++11 specializations for cv types were not required in some headers, which led to ambiguity required

[edit] See also

Structured binding (C++17) binds the specified names to sub-objects or tuple elements of the initializer[edit]
obtains the number of elements of a tuple-like type (class template) [edit]
creates a tuple by concatenating any number of tuples (function template) [edit]