utility_tuple_element

utility_tuple_element (튜플 유사 타입의 요소 타입 접근)

std::tuple_element은 튜플 유사(tuple-like) 타입의 특정 위치에 있는 요소의 타입을 컴파일 타임에 알아내기 위한 클래스 템플릿이에요. 이 템플릿은 std::tuple, std::pair, std::array 같은 표준 라이브러리 타입뿐 아니라, 사용자가 직접 정의한 타입에 대해서도 특수화할 수 있어서 구조적 바인딩과 같은 기능을 지원하는 데 사용돼요. 이 페이지에서는 std::tuple_element의 정의, 특수화, 사용 예시를 설명할게요.

출처: cppreference

본문

정의

다음과 같이 <tuple>, <array>, <utility>, <ranges>, <complex> 헤더에 정의되어 있어요.

<tuple> 헤더에 정의됨
<array> 헤더에 정의됨
<utility> 헤더에 정의됨
<ranges> 헤더에 정의됨 (since C++20)
<complex> 헤더에 정의됨 (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)

이 템플릿은 튜플 유사 타입의 요소 타입에 대한 컴파일 타임 인덱스 접근을 제공해요.

std::tuple_element는 핵심 언어와 상호작용해서, 튜플 유사 경우에 구조적 바인딩(structured binding)을 지원할 수 있어요. (since C++17)

특수화

표준 라이브러리는 다음과 같은 표준 라이브러리 타입에 대한 특수화를 제공해요.

std::tuple_element<std::tuple> (C++11) 지정된 요소의 타입을 얻습니다 (클래스 템플릿 특수화) [edit]
std::tuple_element<std::pair> (C++11) pair의 요소 타입을 얻습니다 (클래스 템플릿 특수화) [edit]
std::tuple_element<std::array> (C++11) array의 요소 타입을 얻습니다 (클래스 템플릿 특수화) [edit]
std::tuple_element<std::ranges::subrange> (C++20) std::ranges::subrange의 반복자 또는 센티널 타입을 얻습니다 (클래스 템플릿 특수화) [edit]
std::tuple_element<std::complex> (C++26) std::complex의 기본 실수 및 허수 타입을 얻습니다 (클래스 템플릿 특수화) [edit]

사용자는 프로그램 정의 타입을 튜플 유사하게 만들기 위해 std::tuple_element를 특수화할 수 있어요.

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 ; (since C++14)

참고 사항

기능 테스트 매크로 표준 기능
__cpp_lib_tuple_element_t 201402L (C++14) std::tuple_element_t

예제

#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(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*>);
}

출력:

42

결함 보고

다음의 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었어요.

DR 적용 대상 발표된 동작 올바른 동작
LWG 2212 C++11 일부 헤더에서 cv 타입에 대한 특수화가 요구되지 않아 모호성이 발생했다 요구됨

같이 보기

구조적 바인딩 (C++17) 초기화자의 하위 객체나 튜플 요소에 지정된 이름을 바인딩합니다 [edit]
tuple_size (C++11) 튜플 유사 타입의 요소 개수를 얻습니다 (클래스 템플릿) [edit]
tuple_cat (C++11) 여러 튜플을 연결하여 튜플을 만듭니다 (함수 템플릿) [edit]
tuple_element (C++26) 튜플 유사 타입의 요소 타입에 대한 리플렉션을 얻습니다 (함수) [edit]

더 알아보기 (Learn more)

cppreference