Difference between revisions of "cpp/utility/tuple size"
(Created the page for the primary template and general specializations.) |
m (-`inline`: CWG2387; fmt.) |
||
(14 intermediate revisions by 4 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/utility/navbar}} | {{cpp/utility/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | | + | {{dcl header|array}} |
− | {{dcl header | | + | {{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. | + | @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 {{ | + | @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 | + | {{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 {{ | + | 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 60: | Line 63: | ||
Users may specialize {{tt|std::tuple_size}} for program-defined types to make them tuple-like. Program-defined specializations must meet the requirements above. | Users may specialize {{tt|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. | + | Usually only specialization for cv-unqualified types are needed to be customized. |
− | === Helper variable template === | + | ===Helper variable template=== |
− | {{ddcl | since=c++17 | 1= | + | {{ddcl|header=tuple|since=c++17|1= |
template< class T > | template< class T > | ||
− | + | 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 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
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 > |
(2) | (since C++11) |
template< class T > struct tuple_size< volatile T > |
(3) | (since C++11) (deprecated in C++20) |
template< class T > struct tuple_size< const volatile T > |
(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.
(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 #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:
(C++11) |
obtains the size of
a |
(C++11) |
obtains the size of a pair (class template specialization) |
(C++11) |
obtains the size of an array (class template specialization) |
obtains the size of a std::ranges::subrange (class template specialization) | |
obtains the size of a std::complex (class template specialization) |
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 |
(C++11) |
obtains the element types of a tuple-like type (class template) |
(C++11) |
creates a tuple by concatenating any number of tuples (function template) |