Zserio C++ runtime library  1.0.0
Built for Zserio 2.13.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 <type_traits>
7 #include <memory>
8 #include <vector>
9 
10 #include "zserio/OptionalHolder.h"
11 #include "zserio/AnyHolder.h"
12 #include "zserio/NoInit.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>
35  const AnyHolder<ALLOC>& source, const ALLOC2& allocator);
36 
37 template <typename T, typename ALLOC>
38 T allocatorPropagatingCopy(NoInitT, const T& source, const ALLOC& allocator);
39 
40 template <typename T, typename ALLOC, typename ALLOC2>
42  NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator);
43 
44 namespace detail
45 {
46 
47 // implementation for std::basic_string from old std. libs, that does not fully conform
48 // to C++11. [old-compiler-support]
49 template <typename CharT, typename Traits, typename ALLOC1, typename ALLOC2>
50 std::basic_string<CharT, Traits, ALLOC1> allocatorPropagatingCopyDefault(std::true_type,
51  const std::basic_string<CharT, Traits, ALLOC1>& source, const ALLOC2& allocator)
52 {
53  return std::basic_string<CharT, Traits, ALLOC1>(source.c_str(), source.length(), allocator);
54 }
55 
56 // implementation of copy for vectors of bool from old std. libs, that does not fully
57 // conform to C++11. [old-compiler-support]
58 template <typename ALLOC, typename ALLOC2>
59 std::vector<bool, ALLOC> allocatorPropagatingCopyVec(
60  std::false_type, const std::vector<bool, ALLOC>& source, const ALLOC2& allocator)
61 {
62  std::vector<bool, ALLOC> ret(allocator);
63  ret.reserve(source.size());
64  ret.assign(source.begin(), source.end());
65  return ret;
66 }
67 
68 // implementation of copy for "regular" classes that supports allocator
69 template <typename T, typename ALLOC>
70 T allocatorPropagatingCopyDefault(std::true_type, const T& source, const ALLOC& allocator)
71 {
72  return T(source, allocator);
73 }
74 
75 // implementation of copy for "regular" classes that does not support allocator
76 template <typename T, typename ALLOC>
77 T allocatorPropagatingCopyDefault(std::false_type, const T& source, const ALLOC&)
78 {
79  return source;
80 }
81 
82 // implementation of copy for "regular" classes that supports "PropagateAllocator" copy
83 template <typename T, typename ALLOC>
84 T allocatorPropagatingCopyPropagating(std::true_type, const T& source, const ALLOC& allocator)
85 {
86  return T(PropagateAllocator, source, allocator);
87 }
88 
89 // implementation of copy for "regular" classes that supports "PropagateAllocator" copy
90 template <typename T, typename ALLOC>
91 T allocatorPropagatingCopyPropagating(std::true_type, NoInitT, const T& source, const ALLOC& allocator)
92 {
93  return T(PropagateAllocator, NoInit, source, allocator);
94 }
95 
96 // implementation of copy for "regular" classes that does not support "PropagateAllocator" copy
97 template <typename T, typename ALLOC>
98 T allocatorPropagatingCopyPropagating(std::false_type, const T& source, const ALLOC& allocator)
99 {
100  return allocatorPropagatingCopyDefault(std::uses_allocator<T, ALLOC>(), source, allocator);
101 }
102 
103 // implementation of copy for vectors containing type that supports allocator
104 template <typename T, typename ALLOC, typename ALLOC2>
105 std::vector<T, ALLOC> allocatorPropagatingCopyVec(
106  std::true_type, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
107 {
108  std::vector<T, ALLOC> result(allocator);
109  result.reserve(source.size());
110  std::transform(source.begin(), source.end(), std::back_inserter(result),
111  [&](const T& value){ return allocatorPropagatingCopy(value, allocator); });
112  return result;
113 }
114 
115 // implementation of copy for vectors containing type that supports allocator
116 template <typename T, typename ALLOC, typename ALLOC2>
117 std::vector<T, ALLOC> allocatorPropagatingCopyVec(
118  std::true_type, NoInitT, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
119 {
120  std::vector<T, ALLOC> result(allocator);
121  result.reserve(source.size());
122  std::transform(source.begin(), source.end(), std::back_inserter(result),
123  [&](const T& value) { return allocatorPropagatingCopy(NoInit, value, allocator); });
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>(NoInit, allocatorPropagatingCopy(NoInit, *source, allocator),
170  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(
200  const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
201 {
202  if (source.hasValue())
203  {
204  return AnyHolder<ALLOC>(allocatorPropagatingCopy(source.template get<T>(), allocator),
205  allocator);
206  }
207  else
208  {
209  return AnyHolder<ALLOC>(allocator);
210  }
211 }
212 
213 template <typename T, typename ALLOC, typename ALLOC2>
214 AnyHolder<ALLOC> allocatorPropagatingCopyImpl(
215  NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
216 {
217  if (source.hasValue())
218  {
219  return AnyHolder<ALLOC>(NoInit, allocatorPropagatingCopy(NoInit, source.template get<T>(), allocator),
220  allocator);
221  }
222  else
223  {
224  return AnyHolder<ALLOC>(allocator);
225  }
226 }
227 
228 template <typename T, typename ALLOC, typename ALLOC2>
229 std::vector<T, ALLOC> allocatorPropagatingCopyImpl(
230  const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
231 {
232  return allocatorPropagatingCopyVec(std::uses_allocator<T, ALLOC>(), source, allocator);
233 }
234 
235 template <typename T, typename ALLOC, typename ALLOC2>
236 std::vector<T, ALLOC> allocatorPropagatingCopyImpl(
237  NoInitT, const std::vector<T, ALLOC>& source, const ALLOC2& allocator)
238 {
239  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
240 
241  return allocatorPropagatingCopyVec(std::uses_allocator<T, ALLOC>(), NoInit, source, allocator);
242 }
243 
244 } // namespace detail
245 
254 template <typename T, typename ALLOC>
255 T allocatorPropagatingCopy(const T& source, const ALLOC& allocator)
256 {
257  static_assert(!std::is_same<AnyHolder<ALLOC>, T>::value, "Cannot be used for AnyHolder!");
258 
259  return detail::allocatorPropagatingCopyImpl(source, allocator);
260 }
261 
270 template <typename T, typename ALLOC>
271 T allocatorPropagatingCopy(NoInitT, const T& source, const ALLOC& allocator)
272 {
273  static_assert(!std::is_same<AnyHolder<ALLOC>, T>::value, "Cannot be used for AnyHolder!");
274 
275  return detail::allocatorPropagatingCopyImpl(NoInit, source, allocator);
276 }
277 
286 template <typename T, typename ALLOC, typename ALLOC2>
288  const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
289 {
290  return detail::allocatorPropagatingCopyImpl<T>(source, allocator);
291 }
292 
301 template <typename T, typename ALLOC, typename ALLOC2>
303  NoInitT, const AnyHolder<ALLOC>& source, const ALLOC2& allocator)
304 {
305  static_assert(std::is_constructible<T, NoInitT, T>::value, "Can be used only for parameterized compounds!");
306 
307  return detail::allocatorPropagatingCopyImpl<T>(NoInit, source, allocator);
308 }
309 
310 } // namespace zserio
311 
312 #endif // ZSERIO_ALLOCATOR_PROPAGATING_COPY_H_INC
detail::heap_optional_holder< T, ALLOC > HeapOptionalHolder
constexpr NoInitT NoInit
Definition: NoInit.h:18
constexpr PropagateAllocatorT PropagateAllocator
T allocatorPropagatingCopy(const T &source, const ALLOC &allocator)
constexpr PropagateAllocatorT()=default
detail::inplace_optional_holder< T > InplaceOptionalHolder
bool hasValue() const
Definition: AnyHolder.h:647