Sequoia
Loading...
Searching...
No Matches
AssignmentUtilities.hpp
Go to the documentation of this file.
1
2// Copyright Oliver J. Rosten 2019. //
3// Distributed under the GNU GENERAL PUBLIC LICENSE, Version 3.0. //
4// (See accompanying file LICENSE.md or copy at //
5// https://www.gnu.org/licenses/gpl-3.0.en.html) //
7
8#pragma once
9
20
21#include <memory>
22
23namespace sequoia::impl
24{
25 template<class Excluded, template<class> class TypeToType, class Fn, class... Ts>
26 void invoke_filtered(Fn f, Ts... t)
27 {
28 invoke_with_specified_args(f, make_filtered_sequence<Excluded, TypeToType, Ts...>{}, t...);
29 }
30
31 template<class T>
33 {
34 template<std::invocable<T> AllocGetter>
35 struct mapper
36 {
37 using type = std::invoke_result_t<AllocGetter, T>;
38 };
39 };
40}
41
42namespace sequoia
43{
67 {
69 template<class T, std::invocable<T>... AllocGetters>
70 constexpr static void assign(T& to, const T& from, [[maybe_unused]] AllocGetters... allocGetters)
71 {
72 impl::invoke_filtered<void, impl::type_to_type<T>::template mapper>([&to, &from](auto... filteredAllocGetters){ assign_filtered(to, from, filteredAllocGetters...); }, allocGetters...);
73 }
74
75 private:
76 template<class T, std::invocable<T>... FilteredAllocGetters>
77 constexpr static void assign_filtered(T& to, const T& from, [[maybe_unused]] FilteredAllocGetters... allocGetters)
78 {
79 if constexpr((naive_treatment<T, FilteredAllocGetters>() && ...))
80 {
81 auto tmp{from};
82 to = std::move(tmp);
83 }
84 else
85 {
86 static_assert(consistency<T, FilteredAllocGetters...>());
87
88 T tmp{from, get_allocator(to, from, allocGetters)...};
89 constexpr bool
90 movePropagation{move_propagation<T, FilteredAllocGetters...>()},
91 copyPropagation{copy_propagation<T, FilteredAllocGetters...>()};
92
93 if constexpr (movePropagation || !copyPropagation)
94 {
95 to = std::move(tmp);
96 }
97 else
98 {
99 if constexpr(!swap_propagation<T, FilteredAllocGetters...>())
100 {
101 to.reset(allocGetters(tmp)...);
102 }
103
104 to.swap(tmp);
105 }
106 }
107 }
108
109 template<class T, std::invocable<T> AllocGetter>
110 constexpr static bool naive_treatment() noexcept
111 {
112 using allocator = std::invoke_result_t<AllocGetter, T>;
113 return std::allocator_traits<allocator>::is_always_equal::value;
114 }
115
116 template<class T, std::invocable<T> AllocGetter, std::invocable<T>... AllocGetters>
117 constexpr static bool consistency() noexcept
118 {
119 if constexpr(sizeof...(AllocGetters) > 0)
120 {
121 return (consistent<T, AllocGetter, AllocGetters>() && ...);
122 }
123 else
124 {
125 return true;
126 }
127 }
128
129 template<class T, std::invocable<T> AllocGetterL, std::invocable<T> AllocGetterR>
130 constexpr static bool consistent() noexcept
131 {
132 return (copy_propagation<T, AllocGetterL>() == copy_propagation<T, AllocGetterR>())
133 && (move_propagation<T, AllocGetterL>() == move_propagation<T, AllocGetterR>())
134 && (swap_propagation<T, AllocGetterL>() == swap_propagation<T, AllocGetterR>());
135 }
136
137 template<class T, class AllocGetter>
138 static auto get_allocator(const T& to, const T& from, AllocGetter allocGetter)
139 {
140 if constexpr(copy_propagation<T, AllocGetter>())
141 {
142 return allocGetter(from);
143 }
144 else
145 {
146 return allocGetter(to);
147 }
148 }
149
150 template<class T, class AllocGetter, class... AllocGetters>
151 constexpr static bool copy_propagation() noexcept
152 {
153 using allocator = std::invoke_result_t<AllocGetter, T>;
154 return std::allocator_traits<allocator>::propagate_on_container_copy_assignment::value
155 || std::allocator_traits<allocator>::is_always_equal::value;
156 }
157
158 template<class T, class AllocGetter, class... AllocGetters>
159 constexpr static bool move_propagation() noexcept
160 {
161 using allocator = std::invoke_result_t<AllocGetter, T>;
162 return std::allocator_traits<allocator>::propagate_on_container_move_assignment::value
163 || std::allocator_traits<allocator>::is_always_equal::value;
164 }
165
166 template<class T, class AllocGetter, class... AllocGetters>
167 constexpr static bool swap_propagation() noexcept
168 {
169 using allocator = std::invoke_result_t<AllocGetter, T>;
170 return std::allocator_traits<allocator>::propagate_on_container_swap::value
171 || std::allocator_traits<allocator>::is_always_equal::value;
172 }
173 };
174}
Helper class to assist with copy assignment for allocator-aware types.
Definition: AssignmentUtilities.hpp:67
static constexpr void assign(T &to, const T &from, AllocGetters... allocGetters)
Definition: AssignmentUtilities.hpp:70
Definition: AssignmentUtilities.hpp:36
Definition: AssignmentUtilities.hpp:33