Zserio C++ runtime library  1.0.1
Built for Zserio 2.14.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  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  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  return HeapOptionalHolder<T, ALLOC>(allocatorPropagatingCopy(*source, allocator), allocator);
157  else
158  return HeapOptionalHolder<T, ALLOC>(allocator);
159 }
160 
161 template <typename T, typename ALLOC, typename ALLOC2>
162 HeapOptionalHolder<T, ALLOC> allocatorPropagatingCopyImpl(
163  NoInitT, const HeapOptionalHolder<T, ALLOC>& source, const ALLOC2& allocator)
164 {
165  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
166 
167  if (source.hasValue())
168  {
169  return HeapOptionalHolder<T, ALLOC>(
170  NoInit, allocatorPropagatingCopy(NoInit, *source, allocator), allocator);
171  }
172  else
173  return HeapOptionalHolder<T, ALLOC>(allocator);
174 }
175 
176 template <typename T, typename ALLOC>
177 InplaceOptionalHolder<T> allocatorPropagatingCopyImpl(
178  const InplaceOptionalHolder<T>& source, const ALLOC& allocator)
179 {
180  if (source.hasValue())
181  return InplaceOptionalHolder<T>(allocatorPropagatingCopy(*source, allocator));
182  else
183  return InplaceOptionalHolder<T>();
184 }
185 
186 template <typename T, typename ALLOC>
187 InplaceOptionalHolder<T> allocatorPropagatingCopyImpl(
188  NoInitT, const InplaceOptionalHolder<T>& source, const ALLOC& allocator)
189 {
190  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
191 
192  if (source.hasValue())
193  return InplaceOptionalHolder<T>(NoInit, allocatorPropagatingCopy(NoInit, *source, allocator));
194  else
195  return InplaceOptionalHolder<T>();
196 }
197 
198 template <typename T, typename ALLOC, typename ALLOC2>
199 AnyHolder<ALLOC> allocatorPropagatingCopyImpl(const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
200 {
201  if (source.hasValue())
202  {
203  return AnyHolder<ALLOC>(allocatorPropagatingCopy(source.template get<T>(), allocator), allocator);
204  }
205  else
206  {
207  return AnyHolder<ALLOC>(allocator);
208  }
209 }
210 
211 template <typename T, typename ALLOC, typename ALLOC2>
212 AnyHolder<ALLOC> allocatorPropagatingCopyImpl(NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
213 {
214  if (source.hasValue())
215  {
216  return AnyHolder<ALLOC>(
217  NoInit, allocatorPropagatingCopy(NoInit, 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 std::vector<T, ALLOC> allocatorPropagatingCopyImpl(const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
227 {
228  return allocatorPropagatingCopyVec(std::uses_allocator<T, ALLOC>(), source, allocator);
229 }
230 
231 template <typename T, typename ALLOC, typename ALLOC2>
232 std::vector<T, ALLOC> allocatorPropagatingCopyImpl(
233  NoInitT, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
234 {
235  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
236 
237  return allocatorPropagatingCopyVec(std::uses_allocator<T, ALLOC>(), NoInit, source, allocator);
238 }
239 
240 } // namespace detail
241 
250 template <typename T, typename ALLOC>
251 T allocatorPropagatingCopy(const T& source, const ALLOC& allocator)
252 {
253  static_assert(!std::is_same<AnyHolder<ALLOC>, T>::value, "Cannot be used for AnyHolder!");
254 
255  return detail::allocatorPropagatingCopyImpl(source, allocator);
256 }
257 
266 template <typename T, typename ALLOC>
267 T allocatorPropagatingCopy(NoInitT, const T& source, const ALLOC& allocator)
268 {
269  static_assert(!std::is_same<AnyHolder<ALLOC>, T>::value, "Cannot be used for AnyHolder!");
270 
271  return detail::allocatorPropagatingCopyImpl(NoInit, source, allocator);
272 }
273 
282 template <typename T, typename ALLOC, typename ALLOC2>
283 AnyHolder<ALLOC> allocatorPropagatingCopy(const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
284 {
285  return detail::allocatorPropagatingCopyImpl<T>(source, allocator);
286 }
287 
296 template <typename T, typename ALLOC, typename ALLOC2>
297 AnyHolder<ALLOC> allocatorPropagatingCopy(NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
298 {
299  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
300 
301  return detail::allocatorPropagatingCopyImpl<T>(NoInit, source, allocator);
302 }
303 
304 } // namespace zserio
305 
306 #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