Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
swap.hpp
Go to the documentation of this file.
1// parasoft-begin-suppress AUTOSAR-A2_8_1-a-2 "False positive: also defines arene::base::swap"
2
3// Copyright 2024, Toyota Motor Corporation
4//
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UTILITY_SWAP_HPP_
7#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UTILITY_SWAP_HPP_
8
9// IWYU pragma: private, include "arene/base/utility.hpp"
10// IWYU pragma: friend "(arene/base(?!/tests)|stdlib/include/stdlib_detail)/.*"
11
12// parasoft-begin-suppress AUTOSAR-A16_2_2-a-2 "Arene Base aggregate headers permitted by A16-2-2 Permit #1"
13#include "arene/base/compiler_support/attributes.hpp"
14#include "arene/base/compiler_support/cpp14_inline.hpp"
15#include "arene/base/constraints/constraints.hpp"
16#include "arene/base/stdlib_choice/cstddef.hpp"
17#include "arene/base/stdlib_choice/enable_if.hpp"
18#include "arene/base/stdlib_choice/move.hpp"
19#include "arene/base/type_traits/is_swappable.hpp"
20// parasoft-end-suppress AUTOSAR-A16_2_2-a-2
21
22namespace arene {
23namespace base {
24
25namespace swap_detail {
26
27/// @brief Poison pill definition of @c swap
28///
29/// This is to ensure that @c swap_fn_impl only looks for a function declaration
30/// and does not pick up some other global object named @c swap
31///
32// parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
33template <class>
34auto swap() -> void = delete;
35// parasoft-end-suppress AUTOSAR-M3_3_2-a-2
36
37/// @brief CPO implementation of @c arene::base::swap .
38/// @see arene::base::swap
39class swap_fn_impl {
40 // parasoft-begin-suppress AUTOSAR-M3_3_2-a-2 "False positive: inline function used in multiple translation units"
41 ///
42 /// @brief specialization for when the input does not have an ADL-discoverable @c swap implementation.
43 ///
44 /// @tparam T type of the elements to swap. Must satisfy @c is_default_swappable_v .
45 /// @param lhs element to swap
46 /// @param rhs element to swap
47 /// @post @c lhs 's state will be as if it had been move-assigned from @c rhs , and vise-versa.
48 template <typename T, constraints<std::enable_if_t<is_default_swappable_v<T>>> = nullptr>
49 static constexpr void default_swap(T& lhs, T& rhs) noexcept(is_nothrow_default_swappable_v<T>) {
50 auto temp = std::move(lhs);
51 lhs = std::move(rhs);
52 rhs = std::move(temp);
53 }
54 // parasoft-end-suppress AUTOSAR-M3_3_2-a-2
55
56 public:
57 ///
58 /// @brief Overload for non-c-array types that provide ADL swap.
59 ///
60 /// @tparam T type of the elements to swap. Must satisfy @c is_swappable_v .
61 /// @param lhs element to swap.
62 /// @param rhs element to swap.
63 /// @post @c lhs and @c rhs will have had their states exchanged via an unqualified call to @c swap.
64 ///
65 template <typename T, constraints<std::enable_if_t<is_adl_swappable_v<T>>> = nullptr>
66 constexpr void operator()(T& lhs, T& rhs) const noexcept(noexcept(swap(lhs, rhs))) {
67 swap(lhs, rhs);
68 }
69 ///
70 /// @brief Overload for non-c-array types that do not provide ADL swap.
71 ///
72 /// @tparam T type of the elements to swap. Must satisfy @c is_swappable_v .
73 /// @param lhs element to swap.
74 /// @param rhs element to swap.
75 /// @post @c lhs and @c rhs will have had their states exchanged via an unqualified call to @c swap.
76 ///
77 template <
78 typename T,
79 constraints<std::enable_if_t<!is_adl_swappable_v<T>>, std::enable_if_t<is_default_swappable_v<T>>> = nullptr>
80 constexpr void operator()(T& lhs, T& rhs) const noexcept(noexcept(default_swap(lhs, rhs))) {
81 default_swap(lhs, rhs);
82 }
83
84 ///
85 /// @brief Overload for c-array types.
86 ///
87 /// @tparam T type of the elements to swap. Must satisfy @c is_swappable_v .
88 /// @param lhs c-array of elements to swap.
89 /// @param rhs c-array elements to swap.
90 /// @post @c lhs and @c rhs will have their elements, in order, exchanged via an unqualified call to @c swap.
91 ///
92 template <class T, std::size_t N, constraints<std::enable_if_t<is_swappable_v<T>>> = nullptr>
93 // NOLINTNEXTLINE(hicpp-avoid-c-arrays) explicitly providing c-array support
94 constexpr void operator()(T (&lhs)[N], T (&rhs)[N]) const noexcept(is_nothrow_swappable_v<T>) {
95 for (std::size_t idx{}; idx < N; ++idx) {
96 (*this)(lhs[idx], rhs[idx]);
97 }
98 }
99};
100
101} // namespace swap_detail
102
103inline namespace swap_cpo {
104///
105/// @brief A Customization Point Object implementation of the @c constexpr compatible @c std::swap from C++17.
106///
107/// @tparam T type of the elements to swap.
108/// @param lhs element(s) to swap.
109/// @param rhs element(s) to swap.
110/// @post @c lhs and @c rhs will have had their states exchanged by one of the described methods.
111///
112/// Functionally equivalent to @c std::swap , including support for c-arrays. Unlike @c std::swap , @c arene::base::swap
113/// is implemented as a _Customization Point Object_. This means it has the following properties:
114///
115/// 1. It supports user customizations directly, performing discovery of @c swap customizations automatically.
116/// Customizations are given the following preference:
117/// 1. ADL-discovered @c swap(lhs,rhs) , if it exists.
118/// 2. The default swap implementation, equivalent to @c std::swap .
119/// 2. It is a function object, so it can be used directly in APIs which consume functors without the need of a wrapper.
120/// 3. It will never be discoverable via ADL. This avoids ambiguous overload resolution problems with types in
121/// @c arene::base which provide customizations of @c swap .
122///
123/// This allow simplification of user code. When using @c std::swap in a generic context, best practice requires the
124/// following pattern in order to allow ADL discovery of @c swap customizations while falling back to the generic @c
125/// @c std::swap implementation for the default case:
126///
127/// @snippet docs/examples/utility_examples.cpp swap_old_usage_example
128
129// parasoft-begin-suppress CERT_CPP-DCL56-a-3 "False positive: variable is initialized"
130/// This is easy to forget. With @c arene::base::swap , this becomes simply:
131///
132/// @snippet docs/examples/utility_examples.cpp swap_new_usage_example
133///
134///
135// Marked maybe unused because gcc doesn't see through this alias being called for some reason.
136ARENE_MAYBE_UNUSED static constexpr auto const& swap =
137 ::arene::base::detail::cpp14_inline_static_const<swap_detail::swap_fn_impl>::value;
138// parasoft-end-suppress CERT_CPP-DCL56-a-3
139} // namespace swap_cpo
140
141} // namespace base
142} // namespace arene
143
144#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_UTILITY_SWAP_HPP_
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10