Zserio C++ runtime library  1.1.0
Built for Zserio 2.15.0
AllocatorPropagatingCopy.h
Go to the documentation of this file.
1 #ifndef ZSERIO_ALLOCATOR_PROPAGATING_COPY_H_INC
2 #define ZSERIO_ALLOCATOR_PROPAGATING_COPY_H_INC
3 
4 #include <algorithm>
5 #include <iterator>
6 #include <memory>
7 #include <type_traits>
8 #include <vector>
9 
10 #include "zserio/AnyHolder.h"
11 #include "zserio/NoInit.h"
12 #include "zserio/OptionalHolder.h"
13 
14 namespace zserio
15 {
16 
21 {
22  constexpr explicit PropagateAllocatorT() = default;
23 };
24 
29 
30 template <typename T, typename ALLOC>
31 T allocatorPropagatingCopy(const T& source, const ALLOC& allocator);
32 
33 template <typename T, typename ALLOC, typename ALLOC2>
34 AnyHolder<ALLOC> allocatorPropagatingCopy(const AnyHolder<ALLOC>& source, const ALLOC2& allocator);
35 
36 template <typename T, typename ALLOC>
37 T allocatorPropagatingCopy(NoInitT, const T& source, const ALLOC& allocator);
38 
39 template <typename T, typename ALLOC, typename ALLOC2>
40 AnyHolder<ALLOC> allocatorPropagatingCopy(NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator);
41 
42 namespace detail
43 {
44 
45 // implementation for std::basic_string from old std. libs, that does not fully conform
46 // to C++11. [old-compiler-support]
47 template <typename CharT, typename Traits, typename ALLOC1, typename ALLOC2>
48 std::basic_string<CharT, Traits, ALLOC1> allocatorPropagatingCopyDefault(
49  std::true_type, const std::basic_string<CharT, Traits, ALLOC1>& source, const ALLOC2& allocator)
50 {
51  return std::basic_string<CharT, Traits, ALLOC1>(source.c_str(), source.length(), allocator);
52 }
53 
54 // implementation of copy for vectors of bool from old std. libs, that does not fully
55 // conform to C++11. [old-compiler-support]
56 template <typename ALLOC, typename ALLOC2>
57 std::vector<bool, ALLOC> allocatorPropagatingCopyVec(
58  std::false_type, const std::vector<bool, ALLOC>& source, const ALLOC2& allocator)
59 {
60  std::vector<bool, ALLOC> ret(allocator);
61  ret.reserve(source.size());
62  ret.assign(source.begin(), source.end());
63  return ret;
64 }
65 
66 // implementation of copy for "regular" classes that supports allocator
67 template <typename T, typename ALLOC>
68 T allocatorPropagatingCopyDefault(std::true_type, const T& source, const ALLOC& allocator)
69 {
70  return T(source, allocator);
71 }
72 
73 // implementation of copy for "regular" classes that does not support allocator
74 template <typename T, typename ALLOC>
75 T allocatorPropagatingCopyDefault(std::false_type, const T& source, const ALLOC&)
76 {
77  return source;
78 }
79 
80 // implementation of copy for "regular" classes that supports "PropagateAllocator" copy
81 template <typename T, typename ALLOC>
82 T allocatorPropagatingCopyPropagating(std::true_type, const T& source, const ALLOC& allocator)
83 {
84  return T(PropagateAllocator, source, allocator);
85 }
86 
87 // implementation of copy for "regular" classes that supports "PropagateAllocator" copy
88 template <typename T, typename ALLOC>
89 T allocatorPropagatingCopyPropagating(std::true_type, NoInitT, const T& source, const ALLOC& allocator)
90 {
91  return T(PropagateAllocator, NoInit, source, allocator);
92 }
93 
94 // implementation of copy for "regular" classes that does not support "PropagateAllocator" copy
95 template <typename T, typename ALLOC>
96 T allocatorPropagatingCopyPropagating(std::false_type, const T& source, const ALLOC& allocator)
97 {
98  return allocatorPropagatingCopyDefault(std::uses_allocator<T, ALLOC>(), source, allocator);
99 }
100 
101 // implementation of copy for vectors containing type that supports allocator
102 template <typename T, typename ALLOC, typename ALLOC2>
103 std::vector<T, ALLOC> allocatorPropagatingCopyVec(
104  std::true_type, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
105 {
106  std::vector<T, ALLOC> result(allocator);
107  result.reserve(source.size());
108  (void)std::transform(source.begin(), source.end(), std::back_inserter(result), [&](const T& value) {
109  return allocatorPropagatingCopy(value, allocator);
110  });
111  return result;
112 }
113 
114 // implementation of copy for vectors containing type that supports allocator
115 template <typename T, typename ALLOC, typename ALLOC2>
116 std::vector<T, ALLOC> allocatorPropagatingCopyVec(
117  std::true_type, NoInitT, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
118 {
119  std::vector<T, ALLOC> result(allocator);
120  result.reserve(source.size());
121  (void)std::transform(source.begin(), source.end(), std::back_inserter(result), [&](const T& value) {
122  return allocatorPropagatingCopy(NoInit, value, allocator);
123  });
124  return result;
125 }
126 
127 // implementation of copy for vectors containing type that does not support allocator
128 template <typename T, typename ALLOC, typename ALLOC2>
129 std::vector<T, ALLOC> allocatorPropagatingCopyVec(
130  std::false_type, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
131 {
132  return std::vector<T, ALLOC>(source, allocator);
133 }
134 
135 template <typename T, typename ALLOC>
136 T allocatorPropagatingCopyImpl(const T& source, const ALLOC& allocator)
137 {
138  return allocatorPropagatingCopyPropagating(
139  std::is_constructible<T, PropagateAllocatorT, T, ALLOC>(), source, allocator);
140 }
141 
142 template <typename T, typename ALLOC>
143 T allocatorPropagatingCopyImpl(NoInitT, const T& source, const ALLOC& allocator)
144 {
145  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
146 
147  return allocatorPropagatingCopyPropagating(
148  std::is_constructible<T, PropagateAllocatorT, NoInitT, T, ALLOC>(), NoInit, source, allocator);
149 }
150 
151 template <typename T, typename ALLOC, typename ALLOC2>
152 HeapOptionalHolder<T, ALLOC> allocatorPropagatingCopyImpl(
153  const HeapOptionalHolder<T, ALLOC>& source, const ALLOC2& allocator)
154 {
155  if (source.hasValue())
156  {
157  return HeapOptionalHolder<T, ALLOC>(allocatorPropagatingCopy(*source, allocator), allocator);
158  }
159  else
160  {
161  return HeapOptionalHolder<T, ALLOC>(allocator);
162  }
163 }
164 
165 template <typename T, typename ALLOC, typename ALLOC2>
166 HeapOptionalHolder<T, ALLOC> allocatorPropagatingCopyImpl(
167  NoInitT, const HeapOptionalHolder<T, ALLOC>& source, const ALLOC2& allocator)
168 {
169  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
170 
171  if (source.hasValue())
172  {
173  return HeapOptionalHolder<T, ALLOC>(
174  NoInit, allocatorPropagatingCopy(NoInit, *source, allocator), allocator);
175  }
176  else
177  {
178  return HeapOptionalHolder<T, ALLOC>(allocator);
179  }
180 }
181 
182 template <typename T, typename ALLOC>
183 InplaceOptionalHolder<T> allocatorPropagatingCopyImpl(
184  const InplaceOptionalHolder<T>& source, const ALLOC& allocator)
185 {
186  if (source.hasValue())
187  {
188  return InplaceOptionalHolder<T>(allocatorPropagatingCopy(*source, allocator));
189  }
190  else
191  {
192  return InplaceOptionalHolder<T>();
193  }
194 }
195 
196 template <typename T, typename ALLOC>
197 InplaceOptionalHolder<T> allocatorPropagatingCopyImpl(
198  NoInitT, const InplaceOptionalHolder<T>& source, const ALLOC& allocator)
199 {
200  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
201 
202  if (source.hasValue())
203  {
204  return InplaceOptionalHolder<T>(NoInit, allocatorPropagatingCopy(NoInit, *source, allocator));
205  }
206  else
207  {
208  return InplaceOptionalHolder<T>();
209  }
210 }
211 
212 template <typename T, typename ALLOC, typename ALLOC2>
213 AnyHolder<ALLOC> allocatorPropagatingCopyImpl(const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
214 {
215  if (source.hasValue())
216  {
217  return AnyHolder<ALLOC>(allocatorPropagatingCopy(source.template get<T>(), allocator), allocator);
218  }
219  else
220  {
221  return AnyHolder<ALLOC>(allocator);
222  }
223 }
224 
225 template <typename T, typename ALLOC, typename ALLOC2>
226 AnyHolder<ALLOC> allocatorPropagatingCopyImpl(NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
227 {
228  if (source.hasValue())
229  {
230  return AnyHolder<ALLOC>(
231  NoInit, allocatorPropagatingCopy(NoInit, source.template get<T>(), allocator), allocator);
232  }
233  else
234  {
235  return AnyHolder<ALLOC>(allocator);
236  }
237 }
238 
239 template <typename T, typename ALLOC, typename ALLOC2>
240 std::vector<T, ALLOC> allocatorPropagatingCopyImpl(const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
241 {
242  return allocatorPropagatingCopyVec(std::uses_allocator<T, ALLOC>(), source, allocator);
243 }
244 
245 template <typename T, typename ALLOC, typename ALLOC2>
246 std::vector<T, ALLOC> allocatorPropagatingCopyImpl(
247  NoInitT, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
248 {
249  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
250 
251  return allocatorPropagatingCopyVec(std::uses_allocator<T, ALLOC>(), NoInit, source, allocator);
252 }
253 
254 } // namespace detail
255 
264 template <typename T, typename ALLOC>
265 T allocatorPropagatingCopy(const T& source, const ALLOC& allocator)
266 {
267  static_assert(!std::is_same<AnyHolder<ALLOC>, T>::value, "Cannot be used for AnyHolder!");
268 
269  return detail::allocatorPropagatingCopyImpl(source, allocator);
270 }
271 
280 template <typename T, typename ALLOC>
281 T allocatorPropagatingCopy(NoInitT, const T& source, const ALLOC& allocator)
282 {
283  static_assert(!std::is_same<AnyHolder<ALLOC>, T>::value, "Cannot be used for AnyHolder!");
284 
285  return detail::allocatorPropagatingCopyImpl(NoInit, source, allocator);
286 }
287 
296 template <typename T, typename ALLOC, typename ALLOC2>
297 AnyHolder<ALLOC> allocatorPropagatingCopy(const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
298 {
299  return detail::allocatorPropagatingCopyImpl<T>(source, allocator);
300 }
301 
310 template <typename T, typename ALLOC, typename ALLOC2>
311 AnyHolder<ALLOC> allocatorPropagatingCopy(NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
312 {
313  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
314 
315  return detail::allocatorPropagatingCopyImpl<T>(NoInit, source, allocator);
316 }
317 
318 } // namespace zserio
319 
320 #endif // ZSERIO_ALLOCATOR_PROPAGATING_COPY_H_INC
constexpr NoInitT NoInit
Definition: NoInit.h:18
constexpr PropagateAllocatorT PropagateAllocator
T allocatorPropagatingCopy(const T &source, const ALLOC &allocator)
constexpr PropagateAllocatorT()=default