Namespaces
Variants

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

cppreference.net에서
 
 
유틸리티 라이브러리
일반 유틸리티
관계 연산자 (C++20에서 폐지)
정수 비교 함수
(C++20)(C++20)(C++20)    
(C++20)
swap 및 타입 연산
(C++14)
(C++11)
(C++11)
(C++11)
(C++17)
일반 어휘 타입
(C++11)
(C++17)
(C++17)
(C++17)
(C++11)
(C++17)
(C++23)



 
 
헤더 <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< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 tuple<UTypes...>& other );
(18) (C++23 이후)
(조건부 explicit)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       const tuple<UTypes...>& other );
(19) (C++11 이후)
(C++20부터 constexpr)
(조건부 explicit)
template< class Alloc, class... UTypes >
tuple( std::allocator_arg_t, const Alloc& a,
       tuple<UTypes...>&& other );
(20) (C++11 이후)
(C++20부터 constexpr)
(조건부 explicit)
template< class Alloc, class... UTypes >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 const tuple<UTypes...>&& other );
(21) (C++23 이후)
(조건부 explicit)
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 std::pair<U1, U2>& p );
(22) (C++23 이후)
(조건부 explicit)
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
       const std::pair<U1, U2>& p );
(23) (C++11 이후)
(C++20부터 constexpr)
(조건부 explicit)
template< class Alloc, class U1, class U2 >
tuple( std::allocator_arg_t, const Alloc& a,
       std::pair<U1, U2>&& p );
(24) (C++11 이후)
(C++20부터 constexpr)
(조건부 explicit)
template< class Alloc, class U1, class U2 >
constexpr tuple( std::allocator_arg_t, const Alloc& a,
                 const std::pair<U1, U2>&& p );
(25) (C++23 이후)
(조건부 explicit)
template< class Alloc, tuple-like UTuple >
constexpr tuple( std::allocator_arg_t, const Alloc& a, UTuple&& u );
(26) (C++23 이후)
(조건부 explicit)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       const tuple& other );
(27) (C++11 이후)
(C++20부터 constexpr)
template< class Alloc >
tuple( std::allocator_arg_t, const Alloc& a,
       tuple&& other );
(28) (C++11 이후)
(C++20부터 constexpr)

새로운 tuple을 생성한다.

다음 설명에서,

  • i는 [0, sizeof...(Types)) 범위에 있고 순서대로 있으며,
  • Ti는 i번째 타입이고,Types는, 그리고
  • Ui는 i번째 타입이며, 템플릿 매개변수 팩 UTypes에 있고,

여기서 인덱싱은 0부터 시작한다.

1) 기본 생성자. 값 초기화한다 (요소가 있는 경우). sizeof...(Types) == 0이면 기본 생성자는 사소하다.
  • 이 오버로드는 모든 std::is_default_constructible<Ti>::value에 대해 true이 i일 때만 오버로드 해결에 참여한다.
  • 생성자는 적어도 하나의 explicit에 대해 Ti가 {}에서 복사-목록 초기화 가능하지 않은 경우에만 i이다.
2) 직접 생성자. tuple의 각 요소를 해당 매개변수로 초기화한다.
  • 이 오버로드는 sizeof...(Types) >= 1이고 모든 std::is_copy_constructible<Ti>::value에 대해 true이 i일 때만 오버로드 해결에 참여한다.
  • 이 생성자는 적어도 하나의 explicit에 대해 std::is_convertible<const Ti&, Ti>::value이 false인 경우에만 i이다.
3) 변환 생성자. tuple의 각 요소를 std::forward<UTypes>(args)의 해당 값으로 초기화한다.
  • 이 오버로드는 다음 조건이 모두 충족될 때만 오버로드 해결에 참여한다:
    • sizeof...(Types) == sizeof...(UTypes),
    • sizeof...(Types) >= 1,
    • std::is_constructible<Ti, Ui>::value 모든 true에 대해 i가
    • 이고,D를 std::decay<U0>::type(C++20까지)std::remove_cvref_t<U0>(C++20부터)라 할 때,
      • sizeof...(Types) == 1이면, D은 std::tuple이 아니고, 그렇지 않으면,
      • sizeof...(Types) == 2이거나 sizeof...(Types) == 3이면, D가 std::allocator_arg_t가 아니거나, T0이 std::allocator_arg_t이다.
  • 생성자는 적어도 하나의 explicit에 대해 std::is_convertible<Ui, Ti>::value이 false인 경우에만 i이다.
(C++23 이후)
4-7) 변환 생성자. tuple의 각 요소를 other의 해당 요소로 초기화한다.

공식적으로, FWD(other)을 std::forward<decltype(other)>(other)라 하고, 모든 i에 대해 tuple의 i번째 요소를 std::get<i>(FWD(other))로 초기화한다.

  • 이 오버로드는 다음 조건이 모두 충족될 때만 오버로드 해결에 참여한다:
    • sizeof...(Types) == sizeof...(UTypes),
    • std::is_constructible_v<Ti, decltype(std::get<i>(FWD(other)))> 모든 true에 대해 i이
    • 이고,
      • sizeof...(Types)가 1이 아니거나,
      • (Types...이 T로 확장되고 UTypes...이 U로 확장될 때) std::is_convertible_v<decltype(other), T>, std::is_constructible_v<T, decltype(other)>, std::is_same_v<T, U>가 모두 false이다.
  • 이 생성자들은 적어도 하나의 explicit에 대해 std::is_convertible_v<decltype(std::get<i>(FWD(other))), Ti>이 false인 경우에만 i이다.
  • 참조인 요소의 초기화가 임시 객체에 바인딩되는 경우 이 생성자들은 삭제된 것으로 정의된다.
(C++23 이후)
8-11) 쌍 생성자. 각 요소를 p의 해당 요소로부터 생성하여 2-요소 tuple을 생성한다.

공식적으로, FWD(p)을 std::forward<decltype(p)>(p)라 하고, 첫 번째 요소를 std::get<0>(FWD(p))로, 두 번째 요소를 std::get<1>(FWD(p))로 초기화한다.

  • 이 오버로드는 다음 조건이 모두 충족될 때만 오버로드 해결에 참여한다:
    • sizeof...(Types) == 2,
    • std::is_constructible_v<T0, decltype(std::get<0>(FWD(p)))>이 true이고,
    • std::is_constructible_v<T1, decltype(std::get<1>(FWD(p)))>이 true이다.
  • 생성자는 explicit 또는 std::is_convertible_v<decltype(std::get<0>(FWD(p))), T0>이 std::is_convertible_v<decltype(std::get<1>(FWD(p))), T1>인 경우에만 false이다.
  • 참조인 요소의 초기화가 임시 객체에 바인딩되는 경우 이 생성자들은 삭제된 것으로 정의된다.
(C++23 이후)
12) tuple-like 생성자. 각 요소를 u의 해당 요소로부터 생성하여 tuple을 생성한다.

공식적으로, 모든 i에 대해 tuple의 i번째 요소를 std::get<i>(std::forward<UTuple>(u))로 초기화한다.

  • 이 오버로드는 다음 조건이 모두 충족될 때만 오버로드 해결에 참여한다:
    • std::same_as<std::remove_cvref_t<UTuple>, std::tuple>이 false이고,
    • std::remove_cvref_t<UTuple>이 std::ranges::subrange의 특수화가 아니고,
    • sizeof...(Types)이 std::tuple_size_v<std::remove_cvref_t<UTuple>>와 같고,
    • std::is_constructible_v<Ti, decltype(std::get<i>(std::forward<UTuple>(u)))> 모든 true에 대해 i이
    • 이고,
      • sizeof...(Types)이 1이 아니거나,
      • (Types...이 T로 확장될 때) std::is_convertible_v<UTuple, T>와 std::is_constructible_v<T, UTuple>가 모두 false이다.
  • 참조인 요소의 초기화가 임시 객체에 바인딩되는 경우 이 생성자는 삭제된 것으로 정의된다.
13) 암시적으로 정의된 복사 생성자. tuple의 각 요소를 other의 해당 요소로 초기화한다.
  • 이 생성자는 수행하는 모든 연산이 constexpr이면 constexpr이다. 빈 tuple std::tuple<>의 경우 constexpr이다.
  • std::is_copy_constructible<Ti>::value는 모든 true에 대해 i이어야 하며, 그렇지 않으면 동작이 정의되지 않음(C++20까지)프로그램이 비정형(ill-formed)(C++20부터)이다.
14) 암시적으로 정의된 이동 생성자. 모든 i에 대해 tuple의 i번째 요소를 std::forward<Ui>(std::get<i>(other))로 초기화한다.
  • 이 생성자는 수행하는 모든 연산이 constexpr이면 constexpr이다. 빈 tuple std::tuple<>의 경우 constexpr이다.
  • std::is_move_constructible<Ti>::value는 모든 true에 대해 i이어야 하며, 그렇지 않으면 동작이 정의되지 않음(C++20까지)이 오버로드는 오버로드 해결에 참여하지 않음(C++20부터)이다.
15-28) (1-14)와 동일하지만, 각 요소가 uses-allocator 생성을 통해 생성된다는 점이 다르다. 즉, a이 std::uses_allocator<Ui, Alloc>::value인 각 요소의 생성자에 할당자 객체 true가 추가 인수로 전달된다.

매개변수

args - 튜플의 각 요소를 초기화하는 데 사용되는 값들
other - 튜플의 각 요소를 초기화하는 데 사용되는 값들의 튜플
p - 2-튜플의 두 요소를 모두 초기화하는 데 사용되는 값들의 쌍
u - 튜플의 각 요소를 초기화하는 데 사용되는 값들의 tuple-like 객체
a - uses-allocator construction에서 사용할 할당자

참고 사항

조건부 명시적 생성자는 복사 초기화 문맥에서 목록 초기화 구문을 사용하여 튜플을 생성할 수 있게 합니다:

std::tuple<int, int> foo_tuple() 
{
    // return {1, -1};             // N4387 이전에는 오류
    return std::make_tuple(1, -1); // 항상 동작함
}

리스트의 일부 요소가 대상 튜플의 해당 요소로 암시적으로 변환되지 않는 경우, 생성자가 명시적(explicit)이 된다는 점에 유의하십시오:

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, "테스트", -3.14};
    print("값으로 초기화된 t2:", t2);
    std::tuple<char, std::string, int> t3{t2};
    print("암시적으로 변환됨, t3:", t3);
    std::tuple<int, double> t4{std::make_pair
(설명: HTML 태그와 속성은 그대로 유지되었으며, C++ 관련 용어인 `std::make_pair`는 번역되지 않았습니다. 링크 구조와 클래스 속성도 원본 형식을 그대로 보존합니다.)(42, 3.14)};
    print("쌍으로부터 생성됨, t4:", t4);
    // 단일 인자 생성자를 가진 Allocator my_alloc이 주어졌을 때
    // my_alloc(int); my_alloc(1)를 사용하여 벡터에 5개의 int를 할당합니다
    using my_alloc = std::allocator<int>;
    std::vector<int, my_alloc> v{5, 1, my_alloc{/* 1 */}};
    // my_alloc(2)를 사용하여 튜플 내 벡터에 5개의 int를 할당
    std::tuple<int, std::vector<int, my_alloc>, double> t5
        {std::allocator_arg, my_alloc{/* 2 */}, 42, v, -3.14};
    print("할당자로 구성됨, t5:", t5);
}

가능한 출력:

값 초기화, t1: (0, "", 0)
값으로 초기화, t2: (42, "Test", -3.14)
암시적 변환, t3: ('*', "Test", -3)
pair로부터 생성, t4: (42, 3.14)
할당자로 생성, t5: (42, {1,1,1,1,1}, -3.14)

결함 보고서

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

DR 적용 대상 게시된 동작 올바른 동작
LWG 2510 C++11 기본 생성자가 암시적이었음 조건부 명시적으로 변경됨
LWG 3121 C++11 1-튜플 생성자가 재귀적으로 제약 조건을 확인할 수 있음;
allocator_arg_t 인수가 모호성을 야기함
생성자를 추가로 제약함
생성자
LWG 3158 C++11 기본 생성자에 해당하는
사용자 할당자 생성자가 암시적이었음
조건부 명시적으로 변경됨
LWG 3211 C++11 tuple<> 의 기본 생성자가
trivial인지 여부가 명시되지 않았음
trivial로 요구함
LWG 4045 C++23 tuple-like 생성자가 잠재적으로 댕글링 참조를 생성할 수 있음 삭제된 것으로 정의됨
N4387 C++11 일부 생성자가 명시적이어서 유용한 동작을 방지함 대부분의 생성자가
조건부 명시적으로 변경됨

참고 항목

한 tuple 의 내용을 다른 tuple 에 할당합니다
(public member function)
(C++11)
인자 타입들로 정의된 타입의 tuple 객체를 생성합니다
(function template)
(C++11)
lvalue 참조들의 tuple 을 생성하거나 tuple을 개별 객체들로 풀어냅니다
(function template)
forwarding references 의 tuple 을 생성합니다
(function template)
새로운 pair 를 생성합니다
( std::pair<T1,T2> 의 public member function)