utility_tuple_size
utility_tuple_size (튜플 크기)
std::tuple_size는 튜플과 유사한(tuple-like) 타입의 요소 개수를 컴파일 타임 상수 표현식으로 제공하는 클래스 템플릿이에요. C++11에서 도입되었으며, 구조적 바인딩(Structured Binding)을 지원하는 데 핵심적인 역할을 해요. 표준 라이브러리의 여러 타입에 대해 특수화가 제공되고, 사용자 정의 타입에 대해서도 직접 특수화할 수 있어요.
출처: cppreference
본문
정의
| (C++20부터) | ||
| (C++26부터) |
template < class T > struct tuple_size ; // not defined |
(1) | (C++11부터) |
|---|---|---|
template < class T > struct tuple_size < const T > : std :: integral_constant < std :: size_t , std :: tuple_size < T >:: value > {}; |
(2) | (C++11부터) |
template < class T > struct tuple_size < volatile T > : std :: integral_constant < std :: size_t , std :: tuple_size < T >:: value > {}; |
(3) | (C++11부터) (C++20에서 폐지됨) |
template < class T > struct tuple_size < const volatile T > : std :: integral_constant < std :: size_t , std :: tuple_size < T >:: value > {}; |
(4) | (C++11부터) (C++20에서 폐지됨) |
튜플과 유사한 타입의 요소 개수를 컴파일 타임 상수 표현식으로 제공해요.
std::tuple_size는 핵심 언어와 상호작용해요. 튜플과 유사한 경우 구조적 바인딩 지원을 제공할 수 있어요. (2)-(4)는 SFINAE 친화적이에요. std::tuple_size<T>::value가 비평가 피연산자(unevaluated operand)로 취급될 때 ill-formed라면, 이들은 value 멤버를 제공하지 않아요. 접근 검사는 tuple_size 및 T와 무관한 컨텍스트에서 수행된 것처럼 이루어져요. 표현식의 즉시 컨텍스트(immediate context)의 유효성만 고려돼요. 이를 통해 다음이 가능해요:
#include <utility>
struct X { int a , b ; };
const auto [ x , y ] = X (); // structured binding declaration first attempts
// tuple_size<const X> which attempts to use
// tuple_size<X>::value, then soft error
// encountered, binds to public data members
(C++17부터)
특수화 (Specializations)
표준 라이브러리는 표준 라이브러리 타입에 대해 다음과 같은 특수화를 제공해요:
std::tuple_size<std::tuple> (C++11) |
튜플의 크기를 얻어요 (클래스 템플릿 특수화) |
|---|---|
std::tuple_size<std::pair> (C++11) |
pair의 크기를 얻어요 (클래스 템플릿 특수화) |
std::tuple_size<std::array> (C++11) |
배열의 크기를 얻어요 (클래스 템플릿 특수화) |
std::tuple_size<std::ranges::subrange> (C++20) |
std::ranges::subrange의 크기를 얻어요 (클래스 템플릿 특수화) |
std::tuple_size<std::complex> (C++26) |
std::complex의 크기를 얻어요 (클래스 템플릿 특수화) |
std::tuple_size의 모든 특수화는 어떤 N에 대해 기본 특성(base characteristic)이 std::integral_constant<std::size_t, N>인 UnaryTypeTrait를 만족해요.
사용자는 프로그램 정의 타입이 튜플처럼 동작하도록 std::tuple_size를 특수화할 수 있어요. 프로그램 정의 특수화는 위 요구 사항을 충족해야 해요.
일반적으로 cv 한정이 없는 타입에 대한 특수화만 사용자 정의하면 돼요.
헬퍼 변수 템플릿 (Helper variable template)
template < class T > constexpr std :: size_t tuple_size_v = tuple_size < T >:: value ; |
(C++17부터) |
std::integral_constant에서 상속됨
멤버 상수
value [static] |
표준 특수화의 경우, 튜플과 유사한 타입 T의 요소 개수 (공개 정적 멤버 상수) |
|---|
멤버 함수
operator std::size_t |
객체를 std::size_t로 변환하고 value를 반환해요 (공개 멤버 함수) |
|---|---|
operator() (C++14) |
value를 반환해요 (공개 멤버 함수) |
멤버 타입
| 타입 | 정의 |
|---|---|
value_type |
std::size_t |
type |
std::integral_constant<std::size_t, value> |
예제 (Example)
#include <array>
#include <cstddef>
#include <ranges>
#include <tuple>
#include <type_traits>
#include <utility>
template<class T, std::size_t Size>
struct Arr
{
T data[Size];
};
// Program-defined specialization of std::tuple_size:
template<class T, std::size_t Size>
struct std::tuple_size<Arr<T, Size>>
: public std::integral_constant<std::size_t, Size>
{};
int main()
{
using tuple1 = std::tuple<int, char, double>;
static_assert(3 == std::tuple_size_v<tuple1>); // uses using template (C++17)
using array3x4 = std::array<std::array<int, 3>, 4>;
static_assert(4 == std::tuple_size<array3x4>{}); // uses operator std::size_t
using pair = std::pair<tuple1, array3x4>;
static_assert(2 == std::tuple_size<pair>()); // uses operator()
using sub = std::ranges::subrange<char*, char*>;
static_assert(2 == std::tuple_size<sub>::value);
using Arr5 = Arr<int, 5>;
static_assert(5 == std::tuple_size_v<Arr5>);
}
결함 보고서 (Defect reports)
다음 동작 변경 결함 보고서는 이전에 발표된 C++ 표준에 소급 적용되었어요.
| DR | 적용 대상 | 발표된 동작 | 올바른 동작 |
|---|---|---|---|
| LWG 2212 | C++11 | cv 타입에 대한 특수화가 일부 헤더에서 요구되지 않아 모호성이 발생했음 | 요구됨 |
같이 보기 (See also)
| 구조적 바인딩 (C++17) | 지정된 이름을 초기화자의 하위 객체 또는 튜플 요소에 바인딩해요 |
|---|---|
tuple_element (C++11) |
튜플과 유사한 타입의 요소 타입을 얻어요 (클래스 템플릿) |
tuple_cat (C++11) |
여러 튜플을 연결하여 튜플을 만들어요 (함수 템플릿) |
tuple_size (C++26) |
반영된 튜플과 유사한 타입의 크기를 반환해요 (함수) |