Namespaces
Variants
Views
Actions

Difference between revisions of "cpp/utility/tuple size"

From cppreference.com
< cpp‎ | utility
m (Helper variable template: ~)
m (-`inline`: CWG2387; fmt.)
 
(10 intermediate revisions by 4 users not shown)
Line 2: Line 2:
 
{{cpp/utility/navbar}}
 
{{cpp/utility/navbar}}
 
{{dcl begin}}
 
{{dcl begin}}
{{dcl header | tuple}}
+
{{dcl header|array}}
{{dcl header | array}}
+
{{dcl header|tuple}}
{{dcl header | utility}}
+
{{dcl header|utility}}
{{dcl header | ranges | notes={{mark since c++20}} }}
+
{{dcl header|ranges|notes={{mark since c++20}}}}
{{dcl | num=1 | since=c++11 |1=
+
{{dcl header|complex|notes={{mark since c++26}}}}
 +
{{dcl|num=1|since=c++11|1=
 
template< class T >
 
template< class T >
 
struct tuple_size; // not defined
 
struct tuple_size; // not defined
 
}}
 
}}
{{dcl | num=2 | since=c++11 |1=
+
{{dcl|num=2|since=c++11|1=
 
template< class T >
 
template< class T >
 
struct tuple_size< const T >
 
struct tuple_size< const T >
     : std::integral_constant<std::size_t, std::tuple_size<T>::value> { };
+
     : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
 
}}
 
}}
{{dcl | num=3 | since=c++11 | deprecated=c++20 |1=
+
{{dcl|num=3|since=c++11|deprecated=c++20|1=
 
template< class T >
 
template< class T >
 
struct tuple_size< volatile T >
 
struct tuple_size< volatile T >
     : std::integral_constant<std::size_t, std::tuple_size<T>::value> { };
+
     : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
 
}}
 
}}
{{dcl | num=4 | since=c++11 | deprecated=c++20 |1=
+
{{dcl|num=4|since=c++11|deprecated=c++20|1=
 
template< class T >
 
template< class T >
 
struct tuple_size< const volatile T >
 
struct tuple_size< const volatile T >
     : std::integral_constant<std::size_t, std::tuple_size<T>::value> { };
+
     : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
 
}}
 
}}
 
{{dcl end}}
 
{{dcl end}}
  
Provides access to the number of elements in a tuple-like type as a compile-time constant expression.
+
Provides access to the number of elements in a {{lt|cpp/utility/tuple/tuple-like}} type as a compile-time constant expression.
  
@1@ The primary template is not defined. A explicit (full) or partial specialization is required to make a type tuple-like.
+
@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 a cv-qualified types reuse the {{tt|value}} from the corresponding cv-unqualified versions by default.
+
@2-4@ Specializations for a cv-qualified types reuse the {{c|value}} from the corresponding cv-unqualified versions by default.
  
 
{{rrev|since=c++17|
 
{{rrev|since=c++17|
{{tt|std::tuple_size}} interacts with the core language: it can provide [[cpp/language/structured binding|structured binding]] support in the tuple-like case.
+
{{tt|std::tuple_size}} interacts with the core language: it can provide {{lt|cpp/language/structured binding}} support in the tuple-like case.
  
{{v|2-4}} are SFINAE-friendly: if {{c|std::tuple_size<T>::value}} is  
+
{{v|2-4}} are SFINAE-friendly: if {{c|std::tuple_size<T>::value}} is
ill-formed when treated as an unevaluated operand, they do not provide the member {{tt|value}}. Access checking is performed as if in a context unrelated to {{tt|tuple_size}} and {{tt|T}}. Only the validity of the immediate context of the expression is considered. This allows
+
ill-formed when treated as an unevaluated operand, they do not provide the member {{c|value}}. Access checking is performed as if in a context unrelated to {{tt|tuple_size}} and {{tt|T}}. Only the validity of the immediate context of the expression is considered. This allows
 
{{source|1=
 
{{source|1=
 
#include <utility>
 
#include <utility>
 +
 
struct X { int a, b; };
 
struct X { int a, b; };
 
const auto [x, y] = X(); // structured binding declaration first attempts
 
const auto [x, y] = X(); // structured binding declaration first attempts
Line 50: Line 52:
 
The standard library provides following specializations for standard library types:
 
The standard library provides following specializations for standard library types:
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/utility/tuple/dsc tuple_size}}
+
{{dsc inc|cpp/utility/tuple/dsc tuple_size}}
{{dsc inc | cpp/utility/pair/dsc tuple_size}}
+
{{dsc inc|cpp/utility/pair/dsc tuple_size}}
{{dsc inc | cpp/container/array/dsc tuple_size}}
+
{{dsc inc|cpp/container/array/dsc tuple_size}}
{{dsc inc | cpp/ranges/subrange/dsc tuple_size}}
+
{{dsc inc|cpp/ranges/subrange/dsc tuple_size}}
 +
{{dsc inc|cpp/numeric/complex/dsc tuple_size}}
 
{{dsc end}}
 
{{dsc end}}
  
Line 62: Line 65:
 
Usually only specialization for cv-unqualified types are needed to be customized.
 
Usually only specialization for cv-unqualified types are needed to be customized.
  
=== Helper variable template ===
+
===Helper variable template===
{{ddcl | header=tuple | since=c++17 | 1=
+
{{ddcl|header=tuple|since=c++17|1=
 
template< class T >
 
template< class T >
inline constexpr std::size_t tuple_size_v = tuple_size<T>::value;
+
constexpr std::size_t tuple_size_v = tuple_size<T>::value;
 
}}
 
}}
  
{{cpp/types/integral_constant/inherit2 | for a standard specialization, the number of elements in the tuple-like type {{tt|T}} |std::size_t}}
+
{{cpp/types/integral_constant/inherit2|for a standard specialization, the number of elements in the tuple-like type {{tt|T}}|std::size_t}}
  
 
===Example===
 
===Example===
{{example}}
+
{{example
 +
|code=
 +
#include <array>
 +
#include <cstddef>
 +
#include <ranges>
 +
#include <tuple>
 +
#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 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===
 
===Defect reports===
Line 80: Line 114:
 
===See also===
 
===See also===
 
{{dsc begin}}
 
{{dsc begin}}
{{dsc inc | cpp/language/dsc structured binding}}
+
{{dsc inc|cpp/language/dsc structured binding}}
{{dsc inc | cpp/utility/dsc tuple_element}}
+
{{dsc inc|cpp/utility/dsc tuple_element}}
{{dsc inc | cpp/utility/tuple/dsc tuple_cat}}
+
{{dsc inc|cpp/utility/tuple/dsc tuple_cat}}
 
{{dsc end}}
 
{{dsc end}}
  
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}
 
{{langlinks|de|es|fr|it|ja|pt|ru|zh}}

Latest revision as of 09:02, 24 September 2024

 
 
Utilities library
General utilities
Relational operators (deprecated in C++20)
 
Defined in header <array>
Defined in header <tuple>
Defined in header <utility>
Defined in header <ranges>
(since C++20)
Defined in header <complex>
(since C++26)
template< class T >
struct tuple_size; // not defined
(1) (since C++11)
template< class T >

struct tuple_size< const T >

    : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
(2) (since C++11)
template< class T >

struct tuple_size< volatile T >

    : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
(3) (since C++11)
(deprecated in C++20)
template< class T >

struct tuple_size< const volatile T >

    : std::integral_constant<std::size_t, std::tuple_size<T>::value> {};
(4) (since C++11)
(deprecated in C++20)

Provides access to the number of elements in a tuple-like type as a compile-time constant expression.

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 a cv-qualified types reuse the value from the corresponding cv-unqualified versions by default.

std::tuple_size interacts with the core language: it can provide structured binding support in the tuple-like case.

(2-4) are SFINAE-friendly: if std::tuple_size<T>::value is ill-formed when treated as an unevaluated operand, they do not provide the member value. Access checking is performed as if in a context unrelated to tuple_size and T. Only the validity of the immediate context of the expression is considered. This allows

#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
(since C++17)

Contents

[edit] Specializations

The standard library provides following specializations for standard library types:

obtains the size of

a tuple
(class template specialization) [edit]

obtains the size of a pair
(class template specialization) [edit]
obtains the size of an array
(class template specialization) [edit]
obtains the size of a std::ranges::subrange
(class template specialization) [edit]
obtains the size of a std::complex
(class template specialization) [edit]

All specializations of std::tuple_size satisfy UnaryTypeTrait with base characteristic std::integral_constant<std::size_t, N> for some N.

Users may specialize std::tuple_size for program-defined types to make them tuple-like. Program-defined specializations must meet the requirements above.

Usually only specialization for cv-unqualified types are needed to be customized.

[edit] Helper variable template

Defined in header <tuple>
template< class T >
constexpr std::size_t tuple_size_v = tuple_size<T>::value;
(since C++17)

Inherited from std::integral_constant

Member constants

value
[static]
for a standard specialization, the number of elements in the tuple-like type T
(public static member constant)

Member functions

operator std::size_t
converts the object to std::size_t, returns value
(public member function)
operator()
(C++14)
returns value
(public member function)

Member types

Type Definition
value_type std::size_t
type std::integral_constant<std::size_t, value>

[edit] Example

#include <array>
#include <cstddef>
#include <ranges>
#include <tuple>
#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 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>);
}

[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 element types of a tuple-like type
(class template) [edit]
(C++11)
creates a tuple by concatenating any number of tuples
(function template) [edit]