Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
tuple.hpp
Go to the documentation of this file.
1// Copyright 2026, Toyota Motor Corporation
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4
5#ifndef INCLUDE_GUARD_ARENE_BASE_STDLIB_INCLUDE_STDLIB_DETAIL_TUPLE_HPP_
6#define INCLUDE_GUARD_ARENE_BASE_STDLIB_INCLUDE_STDLIB_DETAIL_TUPLE_HPP_
7
8// IWYU pragma: private, include <tuple>
9// IWYU pragma: friend "stdlib_detail/.*"
10
11// parasoft-begin-suppress CERT_CPP-DCL58-a-2 "Part of a standard library implementation"
12// parasoft-begin-suppress AUTOSAR-A17_6_1-a-2 "Part of a standard library implementation"
13
14// parasoft-begin-suppress AUTOSAR-M17_0_3-a "Reserved names are used as part of a standard library implementation"
15// parasoft-begin-suppress CERT_CPP-DCL51-d "Reserved names are used as part of a standard library implementation"
16
17// parasoft-begin-suppress CERT_C-EXP37-a "False positive: The rule does not mention naming all parameters"
18
19#include "arene/base/constraints.hpp"
20#include "arene/base/functional/identity.hpp"
21#include "arene/base/type_list/at.hpp"
22#include "arene/base/type_list/type_list.hpp"
23#include "arene/base/type_manipulation/consume_values.hpp"
24#include "arene/base/type_manipulation/ebo_holder.hpp"
25#include "arene/base/type_traits/all_of.hpp"
26#include "arene/base/type_traits/comparison_traits.hpp"
27#include "arene/base/type_traits/index_of.hpp"
28#include "arene/base/type_traits/is_swappable.hpp"
29#include "arene/base/type_traits/remove_cvref.hpp"
30#include "stdlib/include/stdlib_detail/cstddef.hpp"
31#include "stdlib/include/stdlib_detail/declval.hpp"
32#include "stdlib/include/stdlib_detail/enable_if.hpp"
33#include "stdlib/include/stdlib_detail/forward.hpp"
34#include "stdlib/include/stdlib_detail/integer_sequence.hpp"
35#include "stdlib/include/stdlib_detail/integral_constant.hpp"
36#include "stdlib/include/stdlib_detail/is_assignable.hpp"
37#include "stdlib/include/stdlib_detail/is_constructible.hpp"
38#include "stdlib/include/stdlib_detail/is_copy_assignable.hpp"
39#include "stdlib/include/stdlib_detail/is_copy_constructible.hpp"
40#include "stdlib/include/stdlib_detail/is_default_constructible.hpp"
41#include "stdlib/include/stdlib_detail/is_final.hpp"
42#include "stdlib/include/stdlib_detail/is_move_assignable.hpp"
43#include "stdlib/include/stdlib_detail/is_reference.hpp"
44#include "stdlib/include/stdlib_detail/pair.hpp"
45#include "stdlib/include/stdlib_detail/remove_const.hpp"
46#include "stdlib/include/stdlib_detail/remove_reference.hpp"
47#include "stdlib/include/stdlib_detail/tuple_element.hpp"
48#include "stdlib/include/stdlib_detail/tuple_fwd.hpp"
49#include "stdlib/include/stdlib_detail/tuple_size.hpp"
50
51namespace std {
52
53// parasoft-begin-suppress AUTOSAR-A14_7_2-a "False positive: tuple is defined in the current file"
54
55/// @brief obtain the number of elements in a tuple-like type
56/// @tparam Types parameter pack of element types of a tuple
57template <class... Types>
58class tuple_size<tuple<Types...>> : public integral_constant<size_t, sizeof...(Types)> {};
59
60/// @brief obtain the element type at a given index
61/// @tparam I index to obtain the element type of
62/// @tparam Types parameter pack of element types of a tuple
63/// @note ill-formed if @c I is out of bounds
64///
65template <size_t I, class... Types>
66class tuple_element<I, tuple<Types...>> {
67 public:
68 static_assert(I < sizeof...(Types), "index out of range for the given tuple");
69
70 /// @brief the element type at index @c I
71 using type = arene::base::type_lists::at_t<arene::base::type_list<Types...>, I>;
72};
73
74// parasoft-end-suppress AUTOSAR-A14_7_2-a
75
76/// @brief Constructs a tuple of references to the given arguments.
77/// @tparam Types Types of the arguments.
78/// @param args References to the values to include in the tuple.
79/// @return A tuple containing references to the input arguments.
80template <class... Types>
81constexpr auto tie(Types&... args) noexcept -> tuple<Types&...> {
82 return tuple<Types&...>{args...};
83}
84
85namespace tuple_detail {
86/// @brief poison pill declaration of @c __get_tuple_impl
87///
88/// This is to ensure that @c __get_tuple_impl only looks for a function
89/// declaration and does not pick up some other global object named
90/// @c __get_tuple_impl .
91///
92template <class>
93// NOLINTNEXTLINE(readability-identifier-naming): detail within a standard library implemantation
94auto __get_tuple_impl() -> void = delete;
95} // namespace tuple_detail
96
97// parasoft-begin-suppress AUTOSAR-M3_3_2-a "False positive: inline function used in multiple translation units"
98
99/// @brief access an element of a mutable lvalue reference to a @c tuple
100/// @tparam I index of the element to access
101/// @tparam Types types of the @c tuple
102/// @param tup @c tuple to access an element from
103/// @return reference to the @c I'th element of @c tup
104template <size_t I, class... Types>
105constexpr auto get(tuple<Types...>& tup) noexcept -> tuple_element_t<I, tuple<Types...>>& {
106 using tuple_detail::__get_tuple_impl;
107
108 return __get_tuple_impl<I>(tup).value();
109}
110
111/// @brief access an element of a const lvalue reference to a @c tuple
112/// @tparam I index of the element to access
113/// @tparam Types types of the @c tuple
114/// @param tup @c tuple to access an element from
115/// @return reference to the @c I'th element of @c tup
116template <size_t I, class... Types>
117constexpr auto get(tuple<Types...> const& tup) noexcept -> tuple_element_t<I, tuple<Types...>> const& {
118 using tuple_detail::__get_tuple_impl;
119
120 // parasoft-begin-suppress AUTOSAR-A5_2_3-a "tup data not accessed, and const added back before returning reference"
121 // parasoft-begin-suppress CERT_CPP-EXP55-a "tup data not accessed, and const added back before returning reference"
122 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
123 return __get_tuple_impl<I>(const_cast<tuple<Types...>&>(tup)).value();
124 // parasoft-end-suppress CERT_CPP-EXP55-a
125 // parasoft-end-suppress AUTOSAR-A5_2_3-a
126}
127
128/// @brief access an element of a mutable rvalue reference to a @c tuple
129/// @tparam I index of the element to access
130/// @tparam Types types of the @c tuple
131/// @param tup @c tuple to access an element from
132/// @return reference to the @c I'th element of @c tup
133// parasoft-begin-suppress AUTOSAR-A8_4_6-a "tup variable only used to deduce tuple member to return a reference to"
134// parasoft-begin-suppress AUTOSAR-A8_4_5-a "tup variable only used to deduce tuple member to return a reference to"
135// parasoft-begin-suppress AUTOSAR-A12_8_4-a "tup variable only used to deduce tuple member to return a reference to"
136template <size_t I, class... Types>
137constexpr auto get(tuple<Types...>&& tup) noexcept -> tuple_element_t<I, tuple<Types...>>&& {
138 using tuple_detail::__get_tuple_impl;
139 using return_type = tuple_element_t<I, tuple<Types...>>&&;
140
141 return static_cast<return_type>(__get_tuple_impl<I>(tup).value());
142}
143// parasoft-end-suppress AUTOSAR-A12_8_4-a
144// parasoft-end-suppress AUTOSAR-A8_4_5-a
145// parasoft-end-suppress AUTOSAR-A8_4_6-a
146
147/// @brief access an element of a const rvalue reference to a @c tuple
148/// @tparam I index of the element to access
149/// @tparam Types types of the @c tuple
150/// @param tup @c tuple to access an element from
151/// @return reference to the @c I'th element of @c tup
152template <size_t I, class... Types>
153constexpr auto get(tuple<Types...> const&& tup) noexcept -> tuple_element_t<I, tuple<Types...>> const&& {
154 using tuple_detail::__get_tuple_impl;
155 using return_type = tuple_element_t<I, tuple<Types...>> const&&;
156
157 // parasoft-begin-suppress AUTOSAR-A5_2_3-a "tup data not accessed, and const added back before returning reference"
158 // parasoft-begin-suppress CERT_CPP-EXP55-a "tup data not accessed, and const added back before returning reference"
159 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-const-cast)
160 return static_cast<return_type>(__get_tuple_impl<I>(const_cast<tuple<Types...>&>(tup)).value());
161 // parasoft-end-suppress CERT_CPP-EXP55-a
162 // parasoft-end-suppress AUTOSAR-A5_2_3-a
163}
164
165/// @brief access an element of an lvalue reference to a @c tuple
166/// @tparam T type of the element to access; must occur exactly once within @c tuple
167/// @tparam Types types of the @c tuple
168/// @param tup @c tuple to access an element from
169/// @return reference to the only occurrence of @c T within @c tup
170template <class T, class... Types>
171constexpr auto get(tuple<Types...>& tup) noexcept -> T& {
172 constexpr size_t first_idx{::arene::base::index_of_v<T, Types...>};
173 constexpr size_t last_idx{::arene::base::last_index_of_v<T, Types...>};
174 static_assert(
175 first_idx == last_idx,
176 "Type-based std::get<T>(std::tuple<Types...>) can only be used if T appears exactly once in Types, but it "
177 "appears multiple times"
178 );
179
180 return get<first_idx>(tup);
181}
182
183/// @brief access an element of a const lvalue reference to a @c tuple
184/// @tparam T type of the element to access; must occur exactly once within @c tuple
185/// @tparam Types types of the @c tuple
186/// @param tup @c tuple to access an element from
187/// @return reference to the only occurrence of @c T within @c tup
188template <class T, class... Types>
189constexpr auto get(tuple<Types...> const& tup) noexcept -> T const& {
190 constexpr size_t first_idx{::arene::base::index_of_v<T, Types...>};
191 constexpr size_t last_idx{::arene::base::last_index_of_v<T, Types...>};
192 static_assert(
193 first_idx == last_idx,
194 "Type-based std::get<T>(std::tuple<Types...>) can only be used if T appears exactly once in Types, but it "
195 "appears multiple times"
196 );
197
198 return get<first_idx>(tup);
199}
200
201/// @brief access an element of an rvalue reference to a @c tuple
202/// @tparam T type of the element to access; must occur exactly once within @c tuple
203/// @tparam Types types of the @c tuple
204/// @param tup @c tuple to access an element from
205/// @return reference to the only occurrence of @c T within @c tup
206template <class T, class... Types>
207constexpr auto get(tuple<Types...>&& tup) noexcept -> T&& {
208 constexpr size_t first_idx{::arene::base::index_of_v<T, Types...>};
209 constexpr size_t last_idx{::arene::base::last_index_of_v<T, Types...>};
210 static_assert(
211 first_idx == last_idx,
212 "Type-based std::get<T>(std::tuple<Types...>) can only be used if T appears exactly once in Types, but it "
213 "appears multiple times"
214 );
215
216 return get<first_idx>(std::move(tup));
217}
218
219/// @brief access an element of a const rvalue reference to a @c tuple
220/// @tparam T type of the element to access; must occur exactly once within @c tuple
221/// @tparam Types types of the @c tuple
222/// @param tup @c tuple to access an element from
223/// @return reference to the only occurrence of @c T within @c tup
224template <class T, class... Types>
225constexpr auto get(tuple<Types...> const&& tup) noexcept -> T const&& {
226 constexpr size_t first_idx{::arene::base::index_of_v<T, Types...>};
227 constexpr size_t last_idx{::arene::base::last_index_of_v<T, Types...>};
228 static_assert(
229 first_idx == last_idx,
230 "Type-based std::get<T>(std::tuple<Types...>) can only be used if T appears exactly once in Types, but it "
231 "appears multiple times"
232 );
233
234 return get<first_idx>(std::move(tup));
235}
236// parasoft-end-suppress AUTOSAR-M3_3_2-a
237
238namespace tuple_detail {
239
240/// @brief handles reference binding when initializing a reference from a
241/// forwarded argument
242/// @tparam T the target type
243///
244/// This primary template forwards the argument unchanged.
245template <class T, class = void>
247
248/// @brief handles reference binding when initializing a reference from a
249/// forwarded argument
250/// @tparam T the target type without the reference qualifier
251///
252/// When initializing a reference member of type @c T& or @c T&& from an xvalue
253/// (e.g. the result of @c std::forward), [dcl.init.ref] requires
254/// the initializer to be a direct binding and not involve a user-defined
255/// conversion. If the forwarded type is a reference-wrapper-like proxy that
256/// provides a conversion operator to @c T& or @c T&&, the xvalue causes the
257/// direct binding path to be skipped, and the compiler may infer that the
258/// lifetime of the reference is bounded by the lifetime of the temporary,
259/// causing a compilation error.
260///
261/// This specialization ensures that the conversion to @c T& or @c T&& happens
262/// explicitly via @c static_cast before the result is used to initialize
263/// the reference member, producing a reference that satisfies [dcl.init.ref].
264template <class T>
266 public:
267 // parasoft-begin-suppress AUTOSAR-A8_4_6-a-2 "This function object handles a proxy reference conversion"
268 // parasoft-begin-suppress AUTOSAR-A8_4_5-a-2 "This function object handles a proxy reference conversion"
269 // parasoft-begin-suppress AUTOSAR-A12_8_4-a-2 "This function object handles a proxy reference conversion"
270 /// @brief convert the given value to @c T&
271 /// @tparam U the type of the value
272 /// @param value the value to convert
273 /// @return an lvalue reference
274 template <class U>
275 constexpr auto operator()(U&& value) noexcept -> T {
276 return static_cast<T>(value);
277 }
278 // parasoft-end-suppress AUTOSAR-A8_4_6-a-2
279 // parasoft-end-suppress AUTOSAR-A8_4_5-a-2
280 // parasoft-end-suppress AUTOSAR-A12_8_4-a-2
281};
282
283/// @brief contains a single element of a tuple
284/// @tparam I element index
285/// @tparam T element type
286///
287template <size_t I, class T, class = arene::base::constraints<>>
289 /// @brief tag type used to access the value within 'ebo_holder'
291
292 public:
294
295 // parasoft-begin-suppress AUTOSAR-M2_10_1-a "Similar names permitted by M2-10-1 Permit #1"
296
297 // parasoft-begin-suppress AUTOSAR-A10_2_1-a "False positive: redefines member of a privately inherited class"
298 /// @brief obtain the value contained in this leaf
299 /// @return reference to the value
300 ///
301 // parasoft-begin-suppress AUTOSAR-A9_3_1-a "This class doesn't contain/own the data, it wraps it with type info"
302 constexpr auto value() & noexcept -> T& { return this->get_value(base_tag_type{}); }
303 // parasoft-end-suppress AUTOSAR-A9_3_1-a
304
305 /// @brief obtain the value contained in this leaf
306 /// @return reference to the value
307 ///
308 constexpr auto value() const& noexcept -> T const& { return this->get_value(base_tag_type{}); }
309 // parasoft-end-suppress AUTOSAR-A10_2_1-a
310
311 // parasoft-end-suppress AUTOSAR-M2_10_1-a
312};
313
314/// @brief helper used in the implementation of a tuple
315/// @tparam Indices type containing the indices of a tuple
316/// @tparam Types type containing the types of a tuple
317///
318/// This primary template is intentionally not defined.
319///
320template <class Indices, class Types>
321class tuple_impl;
322
323/// @brief alias to the tuple leaf type at index I of a tuple
324/// @tparam I leaf index
325/// @tparam Tuple tuple type, specialization of std::tuple
326template <std::size_t I, class Tuple>
328
329// parasoft-begin-suppress AUTOSAR-M2_10_1-a "Similar names permitted by M2-10-1 Permit #1"
330
331/// @brief helper used to implement move assignment
332/// @tparam Dest The tuple to copy assign to
333/// @tparam Source The tuple to copy assign from
334/// @tparam Indices Parameter pack of indices for indexing the tuples
335/// @param dest The destination tuple
336/// @param source The source tuple
337template <class Dest, class Source, std::size_t... Indices>
338void memberwise_forward_assign(Dest& dest, Source&& source, index_sequence<Indices...>) {
339 ::arene::base::consume_values({std::get<Indices>(dest) = std::get<Indices>(std::forward<Source>(source))...});
340}
341
342/// @brief helper used to implement swap
343/// @tparam Lhs The type of the first tuple to swap
344/// @tparam Rhs The type of the second tuple to swap
345/// @tparam Indices Parameter pack of indices for indexing the tuples
346/// @param lhs The first tupe to swap
347/// @param rhs The second tupe to swap
348template <class Lhs, class Rhs, std::size_t... Indices>
349void memberwise_swap(Lhs& lhs, Rhs&& rhs, index_sequence<Indices...>) {
350 ::arene::base::consume_values({(swap(std::get<Indices>(lhs), std::get<Indices>(std::forward<Rhs>(rhs))), true)...});
351}
352
353// parasoft-end-suppress AUTOSAR-M2_10_1-a
354
355/// @brief determine if a trait predicate is @c true for all pairs of @c T...
356/// and @c U...
357/// @tparam Trait binary predicate type trait to transform @c T... with @c U...
358/// @tparam TupleTypeList type-list containing T types
359/// @tparam List type-list containing U types
360/// @note This is a workaround for pack length expand errors with older GCC
361/// versions
362///
363template <template <class...> class Trait, class TupleTypeList, class List, class = void>
365
366/// @brief determine if a trait predicate is @c true for all pairs of @c T...
367/// and @c U...
368/// @tparam Trait binary predicate type trait to transform @c T... with @c U...
369/// @tparam T types in the destination tuple
370/// @tparam U types paired with @c T...
371/// @note This is a workaround for pack length expand errors with older GCC
372/// versions
373///
374template <template <class...> class Trait, class... T, class... U>
376 Trait,
377 arene::base::type_list<T...>,
378 arene::base::type_list<U...>,
379 enable_if_t<sizeof...(T) == sizeof...(U)>> : public bool_constant<arene::base::all_of_v<Trait<T, U>::value...>> {};
380
381// parasoft-begin-suppress AUTOSAR-A14_5_1-a "False positive: There is no single
382// argument template constructor for 'tuple_impl'"
383// parasoft-begin-suppress AUTOSAR-A12_1_5-a "False positive: Delegating constructors are used everywhere they can be"
384
385/// @brief helper used in the implementation of a tuple
386/// @tparam I parameter pack of indices of a tuple
387/// @tparam T parameter pack of types of a tuple
388///
389template <size_t... I, class... T>
391 // this flat implementation is faster to compile than a recursive implementation
392 : public tuple_leaf<I, T>... {
393 /// @brief determine if a trait predicate is @c true for all pairs of @c T...
394 /// and @c U...
395 /// @tparam Trait binary predicate type trait to transform @c T... with @c U...
396 /// @tparam U types paired with @c T...
397 /// @note This is a workaround for pack length expand errors with older GCC
398 /// versions
399 ///
400 template <template <class...> class Trait, class... U>
401 static constexpr bool are_all_arguments_v{
403 };
404
405 public:
406 // parasoft-begin-suppress AUTOSAR-A12_7_1-a "False positive: =default would have different semantics"
407
408 /// @brief default constructor
409 /// @tparam B template parameter used to check constraints
410 ///
411 /// Value-initializes each element of the tuple
412 ///
413 /// @note Requires:
414 /// * @c is_default_constructible<Ti>::value is @c true for all @c Ti in @c Types...
415 ///
416 template <
418 // avoid GCC9 SFINAE error with 'constraints'
419 class = enable_if_t<B>>
420 constexpr tuple_impl() //
422 : tuple_leaf<I, T>{}... {}
423 // parasoft-end-suppress AUTOSAR-A11_3_1-a
424
425 // parasoft-begin-suppress AUTOSAR-A13_3_1-a "This overload, and the overload
426 // with types 'UTypes&&...', are implemented as specified by the
427 // standard."
428
429 /// @brief direct constructor
430 /// @tparam B template parameter used to check constraints
431 /// @tparam N template parameter used to check constraints
432 /// @param args values to initialize with
433 ///
434 /// Initializes each element of the tuple with the corresponding parameter
435 ///
436 /// @note Requires:
437 /// * @c is_copy_constructible<Ti>::value is @c true for all @c Ti in @c Types...
438 /// * <c> sizeof...(Types) != 0 </c> is @c true
439 ///
440 template <
442 size_t N = sizeof...(T),
443 // avoid GCC9 SFINAE error with 'constraints'
444 class = enable_if_t<(N != 0U) && B>>
445 constexpr explicit tuple_impl(T const&... args) //
447 : tuple_leaf<I, T>{args}... {}
448
449 // parasoft-end-suppress AUTOSAR-A13_3_1-a
450
451 /// @brief converting constructor
452 /// @tparam UTypes parameter pack of types to construct from
453 /// @param args values to initialize with
454 ///
455 /// Initializes each element of the tuple with the corresponding parameter
456 ///
457 /// @note Requires:
458 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
459 /// * @c is_constructible<Ti, Ui&&>::value is @c true for all @c Ti in @c
460 /// Types... and @c Ui in @c UTypes...
461 /// * <c> sizeof...(Types) != 0 </c> is @c true
462 ///
463 template <
464 class... UTypes,
465 // avoid GCC9 SFINAE error with 'constraints'
466 class = enable_if_t<
467 (sizeof...(UTypes) != 0U) && //
469 >>
473
474 // NOLINTBEGIN(hicpp-explicit-conversions)
475
476 // parasoft-begin-suppress AUTOSAR-A13_3_1-a "False positive:
477 // 'tuple<Utypes...>&&' in the other constructor overload is not a forwarding
478 // reference"
479
480 /// @brief copy-from-other-tuple constructor
481 /// @tparam UTypes parameter pack of types to construct from
482 /// @param other @c tuple containing values to initialize with
483 ///
484 /// Initializes each element of the tuple from the values in @c other
485 ///
486 /// @note Requires:
487 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
488 /// * @c is_constructible<Ti, Ui const&>::value is @c true for all @c Ti in @c
489 /// Types... and @c Ui in @c UTypes...
490 /// * <c> sizeof...(Types) != 0 </c> is @c true
491 ///
492 template <
493 class... UTypes,
494 // avoid GCC9 SFINAE error with 'constraints'
495 class = enable_if_t<
496 (sizeof...(UTypes) != 0U) && //
498 >>
499 constexpr tuple_impl(tuple<UTypes...> const& other) //
501 : tuple_impl{get<I>(other)...} {}
502
503 // parasoft-end-suppress AUTOSAR-A13_3_1-a
504
505 /// @brief move-from-other-tuple constructor
506 /// @tparam UTypes parameter pack of types to construct from
507 /// @param other @c tuple containing values to initialize with
508 ///
509 /// Initializes each element of the tuple by forwarding the values in @c other
510 ///
511 /// @note Requires:
512 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
513 /// * @c is_constructible<Ti, Ui&&>::value is @c true for all @c Ti in @c
514 /// Types... and @c Ui in @c UTypes...
515 /// * <c> sizeof...(Types) != 0 </c> is @c true
516 ///
517 template <
518 class... UTypes,
519 // avoid GCC9 SFINAE error with 'constraints'
520 class = enable_if_t<
521 (sizeof...(UTypes) != 0U) && //
523 >>
524 constexpr tuple_impl(tuple<UTypes...>&& other) //
526 : tuple_impl{get<I>(std::move(other))...} {}
527
528 // parasoft-begin-suppress AUTOSAR-A13_3_1-a "False positive:
529 // 'pair<Utypes...>&&' in the other constructor overload is not a forwarding
530 // reference"
531
532 /// @brief copy-from-pair constructor
533 /// @tparam UTypes parameter pack of types to construct from
534 /// @param other @c pair containing values to initialize with
535 ///
536 /// Initializes each element of the tuple with a copy of the values in @c other
537 ///
538 /// @note Requires:
539 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
540 /// * @c is_constructible<Ti, Ui const&>::value is @c true for all @c Ti in @c
541 /// Types... and @c Ui in @c UTypes...
542 ///
543 template <
544 class... UTypes,
545 // avoid GCC9 SFINAE error with 'constraints'
547 >>
548 constexpr tuple_impl(pair<UTypes...> const& other) //
550 : tuple_impl{get<0>(other), get<1>(other)} {}
551
552 // parasoft-end-suppress AUTOSAR-A13_3_1-a
553
554 /// @brief move-from-pair constructor
555 /// @tparam UTypes parameter pack of types to construct from
556 /// @param other @c pair containing values to initialize with
557 ///
558 /// Initializes each element of the tuple with a copy of the values in @c other
559 ///
560 /// @note Requires:
561 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
562 /// * @c is_constructible<Ti, Ui&&>::value is @c true for all @c Ti in @c
563 /// Types... and @c Ui in @c UTypes...
564 ///
565 template <
566 class... UTypes,
567 // avoid GCC9 SFINAE error with 'constraints'
569 >>
570 constexpr tuple_impl(pair<UTypes...>&& other) //
572 : tuple_impl{
575 } {}
576
577 // NOLINTEND(hicpp-explicit-conversions)
578};
579
580// parasoft-end-suppress AUTOSAR-A12_1_5-a
581// parasoft-end-suppress AUTOSAR-A14_5_1-a
582
583/// @brief A type trait to determine the noexcept specification of elementwise equality comparison
584/// @tparam LTuple The left tuple to elementwise compare
585/// @tparam RTuple The right tuple to elementwise compare
586template <class LTuple, class RTuple>
588
589/// @brief A type trait to determine the noexcept specification of elementwise equality comparison
590/// @tparam LTypes The element types of the left tuple to elementwise compare
591/// @tparam RTypes The element types of the right tuple to elementwise compare
592template <class... LTypes, class... RTypes>
595
596/// @brief A type trait to determine the noexcept specification of elementwise less-than comparison
597/// @tparam LTuple The left tuple to elementwise compare
598/// @tparam RTuple The right tuple to elementwise compare
599template <class LTuple, class RTuple>
601
602/// @brief A type trait to determine the noexcept specification of elementwise less-than comparison
603/// @tparam LTypes The element types of the left tuple to elementwise compare
604/// @tparam RTypes The element types of the right tuple to elementwise compare
605template <class... LTypes, class... RTypes>
610
611// We have to disable clang-format here because it can't parse the constraints with the "<" in them.
612// clang-format off
613/// @brief Check if element @c Idx and all subsequent elements of the two tuples are equal
614/// @tparam Idx The Idx to begin checking at
615/// @tparam LTypes The parameter types of the left tuple
616/// @tparam RTypes The parameter types of the right tuple
617/// @return @c true if element @c Idx and all subsequent elements of the two tuples are equal
618template <std::size_t Idx, class... LTypes, class... RTypes,
619 ::arene::base::constraints<enable_if_t<Idx == sizeof...(LTypes)>> = nullptr>
620constexpr auto elements_equal(tuple<LTypes...> const&, tuple<RTypes...> const&) noexcept -> bool {
621 return true;
622}
623
624// parasoft-begin-suppress AUTOSAR-M6_2_2-a "This comparison is defined by the standard."
625/// @brief Check if element @c Idx and all subsequent elements of the two tuples are equal
626/// @tparam Idx The Idx to begin checking at
627/// @tparam LTypes The parameter types of the left tuple
628/// @tparam RTypes The parameter types of the right tuple
629/// @param left The left tuple
630/// @param right The right tuple
631/// @return @c true if element @c Idx and all subsequent elements of the two tuples are equal
632template <std::size_t Idx, class... LTypes, class... RTypes,
633 ::arene::base::constraints<enable_if_t<Idx < sizeof...(LTypes)>> = nullptr>
634constexpr auto elements_equal(tuple<LTypes...> const& left, tuple<RTypes...> const& right)
636 return (get<Idx>(left) == get<Idx>(right)) && ::std::tuple_detail::elements_equal<Idx + 1UL>(left, right);
637}
638// parasoft-end-suppress AUTOSAR-M6_2_2-a
639
640/// @brief Check if the left tuple is less than the right tuple, starting at @c Idx and counting up
641/// @tparam Idx The Idx to begin checking at
642/// @tparam LTypes The parameter types of the left tuple
643/// @tparam RTypes The parameter types of the right tuple
644/// @return @c true if <c>get<Idx>(left) < get<Idx>(right)</c> or if they're equal and
645/// <c>elements_less<Idx + 1>(left, right)</c>
646template <std::size_t Idx, class... LTypes, class... RTypes,
647 ::arene::base::constraints<enable_if_t<Idx == sizeof...(LTypes)>> = nullptr>
648constexpr auto elements_less(tuple<LTypes...> const&, tuple<RTypes...> const&) noexcept -> bool {
649 return false;
650}
651
652/// @brief Check if the left tuple is less than the right tuple, starting at @c Idx and counting up
653/// @tparam Idx The Idx to begin checking at
654/// @tparam LTypes The parameter types of the left tuple
655/// @tparam RTypes The parameter types of the right tuple
656/// @param left The left tuple
657/// @param right The right tuple
658/// @return @c true if <c>get<Idx>(left) < get<Idx>(right)</c> or if they're equal and
659/// <c>elements_less<Idx + 1>(left, right)</c>
660template <std::size_t Idx, class... LTypes, class... RTypes,
661 ::arene::base::constraints<enable_if_t<Idx < sizeof...(LTypes)>> = nullptr>
662constexpr auto elements_less(tuple<LTypes...> const& left, tuple<RTypes...> const& right)
664 if (get<Idx>(left) < get<Idx>(right)) {
665 return true;
666 }
667 if (get<Idx>(right) < get<Idx>(left)) {
668 return false;
669 }
670 return ::std::tuple_detail::elements_less<Idx + 1UL>(left, right);
671}
672// clang-format on
673
674} // namespace tuple_detail
675
676// parasoft-begin-suppress AUTOSAR-M2_10_1-a "Similar names permitted by M2-10-1 Permit #1"
677// parasoft-begin-suppress AUTOSAR-A2_7_3-a "False positive: Declaration *is* preceeded by the @brief tag."
678/// @brief a heterogeneous, fixed-size collection of values
679/// @tparam Types the types of elements that the tuple stores
680template <class... Types>
682 // parasoft-begin-suppress AUTOSAR-A2_10_1-e "False positive: 'impl_type' does not hide an identifier in 'tuple'"
683 /// @brief implementation type that publicly inherits from the individual tuple elements
685 // parasoft-end-suppress AUTOSAR-A2_10_1-e
686
687 // parasoft-begin-suppress AUTOSAR-A11_3_1-a "Hidden friends permitted by A11-3-1 Permit #2"
688 // parasoft-begin-suppress AUTOSAR-M3_3_2-a "False positive: inline function used in multiple translation units"
689 // NOLINTBEGIN(readability-identifier-naming): detail within a standard library implemantation
690
691 /// @brief obtain the @c tuple_leaf element at a specified index
692 /// @tparam I tuple element index
693 /// @param tup reference to a @c tuple
694 /// @return reference to the value containing the @c I 'th element
695 /// @note The SFINAE constraint is to prevent ambiguity for a tuple of tuples.
696 /// Without the constraint, ADL finds this friend through the associated
697 /// classes of the template arguments, causing the inner tuple instantiations'
698 /// friends to also be viable candidates via implicit derived-to-base
699 /// conversion.
700 template <
701 size_t I,
702 class Tuple,
704 friend constexpr auto __get_tuple_impl(Tuple& tup) noexcept -> tuple_detail::tuple_leaf_t<I, Tuple>& {
705 return static_cast<tuple_detail::tuple_leaf_t<I, Tuple>&>(static_cast<impl_type&>(tup));
706 }
707 // parasoft-end-suppress AUTOSAR-M3_3_2-a
708 // parasoft-end-suppress AUTOSAR-A11_3_1-a
709 // NOLINTEND(readability-identifier-naming)
710
711 using impl_type::impl_type;
712
713 // parasoft-begin-suppress AUTOSAR-A2_10_1-e "False positive: 'are_all_arguments_v' does not hide private member
714 // 'are_all_arguments_v' in 'tuple_impl'"
715 /// @brief determine if a trait predicate is @c true for all pairs of @c T...
716 /// and @c U...
717 /// @tparam Trait binary predicate type trait to transform @c T... with @c U...
718 /// @tparam U types paired with @c T...
719 /// @note This is a workaround for pack length expand errors with older GCC
720 /// versions
721 ///
722 template <template <class...> class Trait, class... U>
723 static constexpr bool are_all_arguments_v{
725 };
726 // parasoft-end-suppress AUTOSAR-A2_10_1-e
727
728 // parasoft-begin-suppress AUTOSAR-A2_10_1-e "False positive: 'type_index_sequence' does not hide anything"
729 /// @brief Helper index sequence for @c Types...
730 static constexpr auto type_index_sequence = std::index_sequence_for<Types...>{};
731 // parasoft-end-suppress AUTOSAR-A2_10_1-e
732
733 public:
734 // parasoft-begin-suppress AUTOSAR-A12_8_6-a "False Positive: this is not a base class."
735 /// @brief copy-from-other-tuple assignment
736 /// @tparam UTypes parameter pack of types to assign from
737 /// @param other @c tuple containing values to assign from
738 ///
739 /// Initializes each element of the tuple from the values in @c other
740 ///
741 /// @note Requires:
742 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
743 /// * @c is_assignable<Ti, Ui const&>::value is @c true for all @c Ti in @c
744 /// Types... and @c Ui in @c UTypes...
745 /// * <c> sizeof...(Types) != 0 </c> is @c true
746 ///
747 template <
748 class... UTypes,
749 // avoid GCC9 SFINAE error with 'constraints'
750 class = enable_if_t<
751 (sizeof...(UTypes) != 0U) && //
753 >>
754 auto operator=(tuple<UTypes...> const& other) noexcept(are_all_arguments_v<is_nothrow_assignable, UTypes const&...>)
755 -> tuple& {
756 tuple_detail::memberwise_forward_assign(*this, other, type_index_sequence);
757 return *this;
758 }
759
760 /// @brief move-from-other-tuple assignment
761 /// @tparam UTypes parameter pack of types to move assign from
762 /// @param other @c tuple containing values to move assign from
763 ///
764 /// Initializes each element of the tuple from the values in @c other
765 ///
766 /// @note Requires:
767 /// * <c> sizeof...(Types) == sizeof...(UTypes) </c> is @c true
768 /// * @c is_assignable<Ti, Ui const&>::value is @c true for all @c Ti in @c
769 /// Types... and @c Ui in @c UTypes...
770 /// * <c> sizeof...(Types) != 0 </c> is @c true
771 ///
772 template <
773 class... UTypes,
774 // avoid GCC9 SFINAE error with 'constraints'
775 class = enable_if_t<
776 (sizeof...(UTypes) != 0U) && //
778 >>
779 auto operator=(tuple<UTypes...>&& other) noexcept(are_all_arguments_v<is_nothrow_assignable, UTypes&&...>) -> tuple& {
780 tuple_detail::memberwise_forward_assign(*this, std::move(other), type_index_sequence);
781 return *this;
782 }
783
784 /// @brief copy-assign-from-pair constructor
785 /// @tparam U1 first parameter to assign from
786 /// @tparam U2 second parameter to assign from
787 /// @param other @c pair containing values to initialize with
788 ///
789 /// Initializes each element of the tuple with a copy of the values in @c other
790 ///
791 /// @note Requires:
792 /// * <c> sizeof...(Types) == 2 </c> is @c true
793 /// * @c is_assignable<T1, U1 const&>::value and @c is_assignable<T2, U2 const&>::value is @c true
794 ///
795 template <
796 class U1,
797 class U2,
798 class = enable_if_t<
799 (sizeof...(Types) == 2U) && //
800 are_all_arguments_v<is_assignable, U1 const&, U2 const&> //
801 >>
802 auto operator=(pair<U1, U2> const& other) noexcept(are_all_arguments_v<is_nothrow_assignable, U1 const&, U2 const&>)
803 -> tuple& {
804 tuple_detail::memberwise_forward_assign(*this, other, type_index_sequence);
805 return *this;
806 }
807
808 /// @brief move-assign-from-pair constructor
809 /// @tparam U1 first parameter to assign from
810 /// @tparam U2 second parameter to assign from
811 /// @param other @c pair containing values to initialize with
812 ///
813 /// Initializes each element of the tuple by moving the values in @c other
814 ///
815 /// @note Requires:
816 /// * <c> sizeof...(Types) == 2 </c> is @c true
817 /// * @c is_assignable<T1, U1&&>::value and @c is_assignable<T2, U2&&>::value is @c true
818 ///
819 template <
820 class U1,
821 class U2,
822 class = enable_if_t<
823 (sizeof...(Types) == 2U) && //
825 >>
826 auto operator=(pair<U1, U2>&& other) noexcept(are_all_arguments_v<is_nothrow_assignable, U1&&, U2&&>) -> tuple& {
827 tuple_detail::memberwise_forward_assign(*this, std::move(other), type_index_sequence);
828 return *this;
829 }
830 // parasoft-end-suppress AUTOSAR-A12_8_6-a "False Positive: this is not a base class."
831 // parasoft-end-suppress AUTOSAR-M2_10_1-a
832
833 // parasoft-begin-suppress AUTOSAR-A2_10_1-d "False Positive: 'swap' does not hide anything"
834 /// @brief swap with another tuple
835 /// @param rhs the other tuple to swap @c this with
836 /// @post Equivalent to having invoked @c swap(get<Idx>(*this),get<Idx>(rhs)) for every element.
837 ///
838 /// @note Requires:
839 /// * <c> arene::base::all_of_v<arene::base::is_swappable_v<Types>...> </c> is @c true
840 template <
842 arene::base::constraints<enable_if_t<B>> = nullptr>
846 // parasoft-end-suppress AUTOSAR-A2_10_1-d
847};
848// parasoft-begin-suppress AUTOSAR-A2_7_3-a
849
850/// @brief swap two tuples
851/// @tparam Types The types in the two tuples to be swapped
852/// @param lhs the first tuple to swap
853/// @param rhs the second tuple to swap
854/// @post Equivalent to having invoked @c swap(get<Idx>(lhs),get<Idx>(rhs)) for every element.
855///
856/// @note Requires:
857/// * <c> arene::base::all_of_v<arene::base::is_swappable_v<Types>...> </c> is @c true
858template <
859 class... Types,
861auto swap(tuple<Types...>& lhs, tuple<Types...>& rhs) noexcept(
862 noexcept(std::declval<tuple<Types...>&>().swap(std::declval<tuple<Types...>&>()))
863) -> void {
864 lhs.swap(rhs);
865}
866
867// parasoft-begin-suppress AUTOSAR-A13_5_5-b "This is how the comparison operators are specified in C++14"
868/// @brief Compare two tuples by doing an equality comparison on their elements starting from 0
869/// @tparam LTypes The element types of the left tuple
870/// @tparam RTypes The element types of the right tuple
871/// @param left The left tuple to compare
872/// @param right The right tuple to compare
873/// @return @c true if the elements of @c left all compare equal to those of <c>right</c>, otherwise @c false
874template <class... LTypes, class... RTypes>
875constexpr auto operator==(tuple<LTypes...> const& left, tuple<RTypes...> const& right) noexcept(
876 noexcept(::std::tuple_detail::elements_equal<0UL>(left, right))
877) -> bool {
878 // This is a "Requires" clause in the standard, so it's implemented as a static_assert rather than a constraint.
879 static_assert(sizeof...(LTypes) == sizeof...(RTypes), "Only tuples of the same size can be compared");
880 return ::std::tuple_detail::elements_equal<0UL>(left, right);
881}
882
883/// @brief Compare two tuples by doing an equality comparison on their elements starting from 0
884/// @tparam LTypes The element types of the left tuple
885/// @tparam RTypes The element types of the right tuple
886/// @param left The left tuple to compare
887/// @param right The right tuple to compare
888/// @return @c true if any of the elements of @c left compare unequal to those of <c>right</c>, otherwise @c false
889template <class... LTypes, class... RTypes>
890constexpr auto operator!=(tuple<LTypes...> const& left, tuple<RTypes...> const& right) noexcept(noexcept(left == right))
891 -> bool {
892 return !(left == right);
893}
894
895/// @brief Compare two tuples by doing a lexicographic comparison on their elements starting from 0
896/// @tparam LTypes The element types of the left tuple
897/// @tparam RTypes The element types of the right tuple
898/// @param left The left tuple to compare
899/// @param right The right tuple to compare
900/// @return @c true if a lexicographic comparison of the elements gives "less", otherwise @c false
901template <class... LTypes, class... RTypes>
902constexpr auto operator<(tuple<LTypes...> const& left, tuple<RTypes...> const& right) noexcept(
903 noexcept(::std::tuple_detail::elements_less<0UL>(left, right))
904) -> bool {
905 // This is a "Requires" clause in the standard, so it's implemented as a static_assert rather than a constraint.
906 static_assert(sizeof...(LTypes) == sizeof...(RTypes), "Only tuples of the same size can be compared");
907 return ::std::tuple_detail::elements_less<0UL>(left, right);
908}
909
910/// @brief Compare two tuples by doing a lexicographic comparison on their elements starting from 0
911/// @tparam LTypes The element types of the left tuple
912/// @tparam RTypes The element types of the right tuple
913/// @param left The left tuple to compare
914/// @param right The right tuple to compare
915/// @return @c true if a lexicographic comparison of the elements gives "less" or "equal", otherwise @c false
916template <class... LTypes, class... RTypes>
917constexpr auto operator<=(tuple<LTypes...> const& left, tuple<RTypes...> const& right) noexcept(noexcept(right < left))
918 -> bool {
919 return !(right < left);
920}
921
922/// @brief Compare two tuples by doing a lexicographic comparison on their elements starting from 0
923/// @tparam LTypes The element types of the left tuple
924/// @tparam RTypes The element types of the right tuple
925/// @param left The left tuple to compare
926/// @param right The right tuple to compare
927/// @return @c true if a lexicographic comparison of the elements gives "greater", otherwise @c false
928template <class... LTypes, class... RTypes>
929constexpr auto operator>(tuple<LTypes...> const& left, tuple<RTypes...> const& right) noexcept(noexcept(right < left))
930 -> bool {
931 return right < left;
932}
933
934/// @brief Compare two tuples by doing a lexicographic comparison on their elements starting from 0
935/// @tparam LTypes The element types of the left tuple
936/// @tparam RTypes The element types of the right tuple
937/// @param left The left tuple to compare
938/// @param right The right tuple to compare
939/// @return @c true if a lexicographic comparison of the elements gives "greater" or "equal", otherwise @c false
940template <class... LTypes, class... RTypes>
941constexpr auto operator>=(tuple<LTypes...> const& left, tuple<RTypes...> const& right) noexcept(noexcept(left < right))
942 -> bool {
943 return !(left < right);
944}
945// parasoft-end-suppress AUTOSAR-A13_5_5-b
946
947} // namespace std
948
949#endif // INCLUDE_GUARD_ARENE_BASE_STDLIB_INCLUDE_STDLIB_DETAIL_TUPLE_HPP_
determine if a trait predicate is true for all pairs of T... and U...
Definition tuple.hpp:364
handles reference binding when initializing a reference from a forwarded argument
Definition tuple.hpp:246
contains a single element of a tuple
Definition tuple.hpp:288
constexpr auto value() const &noexcept -> T const &
obtain the value contained in this leaf
Definition tuple.hpp:308
constexpr auto value() &noexcept -> T &
obtain the value contained in this leaf
Definition tuple.hpp:302
a heterogeneous, fixed-size collection of values
Definition tuple.hpp:681
auto operator=(tuple< UTypes... > const &other) noexcept(are_all_arguments_v< is_nothrow_assignable, UTypes const &... >) -> tuple &
copy-from-other-tuple assignment
Definition tuple.hpp:754
auto operator=(pair< U1, U2 > &&other) noexcept(are_all_arguments_v< is_nothrow_assignable, U1 &&, U2 && >) -> tuple &
move-assign-from-pair constructor
Definition tuple.hpp:826
auto operator=(tuple< UTypes... > &&other) noexcept(are_all_arguments_v< is_nothrow_assignable, UTypes &&... >) -> tuple &
move-from-other-tuple assignment
Definition tuple.hpp:779
auto operator=(pair< U1, U2 > const &other) noexcept(are_all_arguments_v< is_nothrow_assignable, U1 const &, U2 const & >) -> tuple &
copy-assign-from-pair constructor
Definition tuple.hpp:802
Definition tuple.hpp:85
constexpr auto elements_less(tuple< LTypes... > const &, tuple< RTypes... > const &) noexcept -> bool
Check if the left tuple is less than the right tuple, starting at Idx and counting up.
Definition tuple.hpp:648
constexpr bool all_elements_nothrow_equality_comparable_v
A type trait to determine the noexcept specification of elementwise equality comparison.
Definition tuple.hpp:587
auto __get_tuple_impl() -> void=delete
poison pill declaration of __get_tuple_impl
constexpr bool all_elements_nothrow_less_than_comparable_v
A type trait to determine the noexcept specification of elementwise less-than comparison.
Definition tuple.hpp:600
void memberwise_forward_assign(Dest &dest, Source &&source, index_sequence< Indices... >)
helper used to implement move assignment
Definition tuple.hpp:338
bool
Check if element Idx and all subsequent elements of the two tuples are equal.
Definition tuple.hpp:635
void memberwise_swap(Lhs &lhs, Rhs &&rhs, index_sequence< Indices... >)
helper used to implement swap
Definition tuple.hpp:349
constexpr auto operator<=(tuple< LTypes... > const &left, tuple< RTypes... > const &right) noexcept(noexcept(right< left)) -> bool
Compare two tuples by doing a lexicographic comparison on their elements starting from 0.
Definition tuple.hpp:917
constexpr auto get(tuple< Types... > const &tup) noexcept -> tuple_element_t< I, tuple< Types... > > const &
access an element of a const lvalue reference to a tuple
Definition tuple.hpp:117
constexpr auto operator>=(tuple< LTypes... > const &left, tuple< RTypes... > const &right) noexcept(noexcept(left< right)) -> bool
Compare two tuples by doing a lexicographic comparison on their elements starting from 0.
Definition tuple.hpp:941
constexpr auto operator<(tuple< LTypes... > const &left, tuple< RTypes... > const &right) noexcept(noexcept(::std::tuple_detail::elements_less< 0UL >(left, right))) -> bool
Compare two tuples by doing a lexicographic comparison on their elements starting from 0.
Definition tuple.hpp:902
constexpr auto operator>(tuple< LTypes... > const &left, tuple< RTypes... > const &right) noexcept(noexcept(right< left)) -> bool
Compare two tuples by doing a lexicographic comparison on their elements starting from 0.
Definition tuple.hpp:929
constexpr auto tie(Types &... args) noexcept -> tuple< Types &... >
Constructs a tuple of references to the given arguments.
Definition tuple.hpp:81
constexpr auto get(tuple< Types... > const &&tup) noexcept -> tuple_element_t< I, tuple< Types... > > const &&
access an element of a const rvalue reference to a tuple
Definition tuple.hpp:153
constexpr auto operator!=(tuple< LTypes... > const &left, tuple< RTypes... > const &right) noexcept(noexcept(left==right)) -> bool
Compare two tuples by doing an equality comparison on their elements starting from 0.
Definition tuple.hpp:890
constexpr auto operator==(tuple< LTypes... > const &left, tuple< RTypes... > const &right) noexcept(noexcept(::std::tuple_detail::elements_equal< 0UL >(left, right))) -> bool
Compare two tuples by doing an equality comparison on their elements starting from 0.
Definition tuple.hpp:875
constexpr auto get(tuple< Types... > &&tup) noexcept -> tuple_element_t< I, tuple< Types... > > &&
access an element of a mutable rvalue reference to a tuple
Definition tuple.hpp:137
constexpr auto get(tuple< Types... > &tup) noexcept -> tuple_element_t< I, tuple< Types... > > &
access an element of a mutable lvalue reference to a tuple
Definition tuple.hpp:105
constexpr auto operator()(::arene::base::result< void, E > const &value) const noexcept(noexcept(hash< E >{}(std::declval< E const & >()))) -> std::size_t
Calculate the hash of a result.
Definition result.hpp:1827