GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
#ifndef ZSERIO_ANY_HOLDER_H_INC |
||
2 |
#define ZSERIO_ANY_HOLDER_H_INC |
||
3 |
|||
4 |
#include <cstddef> |
||
5 |
#include <type_traits> |
||
6 |
|||
7 |
#include "zserio/AllocatorHolder.h" |
||
8 |
#include "zserio/CppRuntimeException.h" |
||
9 |
#include "zserio/NoInit.h" |
||
10 |
#include "zserio/OptionalHolder.h" |
||
11 |
#include "zserio/Types.h" |
||
12 |
#include "zserio/Traits.h" |
||
13 |
#include "zserio/RebindAlloc.h" |
||
14 |
|||
15 |
namespace zserio |
||
16 |
{ |
||
17 |
|||
18 |
namespace detail |
||
19 |
{ |
||
20 |
class TypeIdHolder |
||
21 |
{ |
||
22 |
public: |
||
23 |
using type_id = const int*; |
||
24 |
|||
25 |
template <typename T> |
||
26 |
150266 |
static type_id get() |
|
27 |
{ |
||
28 |
static int currentTypeId; |
||
29 |
|||
30 |
150266 |
return ¤tTypeId; |
|
31 |
} |
||
32 |
}; |
||
33 |
|||
34 |
// Interface for object holders |
||
35 |
template <typename ALLOC> |
||
36 |
66256 |
class IHolder |
|
37 |
{ |
||
38 |
public: |
||
39 |
✗✓✗✓ |
66256 |
virtual ~IHolder() = default; |
40 |
virtual IHolder* clone(const ALLOC& allocator) const = 0; |
||
41 |
virtual IHolder* clone(NoInitT, const ALLOC& allocator) const = 0; |
||
42 |
virtual IHolder* clone(void* storage) const = 0; |
||
43 |
virtual IHolder* clone(NoInitT, void* storage) const = 0; |
||
44 |
virtual IHolder* move(const ALLOC& allocator) = 0; |
||
45 |
virtual IHolder* move(NoInitT, const ALLOC& allocator) = 0; |
||
46 |
virtual IHolder* move(void* storage) = 0; |
||
47 |
virtual IHolder* move(NoInitT, void* storage) = 0; |
||
48 |
virtual void destroy(const ALLOC& allocator) = 0; |
||
49 |
virtual bool isType(detail::TypeIdHolder::type_id typeId) const = 0; |
||
50 |
}; |
||
51 |
|||
52 |
// Base of object holders, holds a value in the inplace_optional_holder |
||
53 |
template <typename T, typename ALLOC> |
||
54 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✓✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗ |
132512 |
class HolderBase : public IHolder<ALLOC> |
55 |
{ |
||
56 |
public: |
||
57 |
template <typename U> |
||
58 |
50057 |
void set(U&& value) |
|
59 |
{ |
||
60 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
50057 |
m_typedHolder = std::forward<U>(value); |
61 |
50057 |
} |
|
62 |
|||
63 |
template <typename U, |
||
64 |
typename std::enable_if<std::is_constructible<U, NoInitT, U>::value, int>::type = 0> |
||
65 |
4 |
void set(NoInitT, U&& value) |
|
66 |
{ |
||
67 |
// inplace_optional_holder constructor to prevent it's implicit constructor |
||
68 |
✓✗✓✗ |
4 |
m_typedHolder.assign(NoInit, inplace_optional_holder<T>(NoInit, std::forward<U>(value))); |
69 |
4 |
} |
|
70 |
|||
71 |
template <typename U, |
||
72 |
typename std::enable_if<!std::is_constructible<U, NoInitT, U>::value, int>::type = 0> |
||
73 |
14 |
void set(NoInitT, U&& value) |
|
74 |
{ |
||
75 |
14 |
m_typedHolder = std::forward<U>(value); |
|
76 |
14 |
} |
|
77 |
|||
78 |
29 |
void setHolder(const inplace_optional_holder<T>& value) |
|
79 |
{ |
||
80 |
29 |
m_typedHolder = value; |
|
81 |
29 |
} |
|
82 |
|||
83 |
16291 |
void setHolder(inplace_optional_holder<T>&& value) |
|
84 |
{ |
||
85 |
16291 |
m_typedHolder = std::move(value); |
|
86 |
16291 |
} |
|
87 |
|||
88 |
template <typename U, |
||
89 |
typename std::enable_if<std::is_constructible<U, NoInitT, U>::value, int>::type = 0> |
||
90 |
6 |
void setHolder(NoInitT, const inplace_optional_holder<U>& value) |
|
91 |
{ |
||
92 |
6 |
m_typedHolder.assign(NoInit, value); |
|
93 |
6 |
} |
|
94 |
|||
95 |
template <typename U, |
||
96 |
typename std::enable_if<std::is_constructible<U, NoInitT, U>::value, int>::type = 0> |
||
97 |
3 |
void setHolder(NoInitT, inplace_optional_holder<U>&& value) |
|
98 |
{ |
||
99 |
3 |
m_typedHolder.assign(NoInit, std::move(value)); |
|
100 |
3 |
} |
|
101 |
|||
102 |
template <typename U, |
||
103 |
typename std::enable_if<!std::is_constructible<U, NoInitT, U>::value, int>::type = 0> |
||
104 |
19 |
void setHolder(NoInitT, const inplace_optional_holder<U>& value) |
|
105 |
{ |
||
106 |
19 |
m_typedHolder = value; |
|
107 |
19 |
} |
|
108 |
|||
109 |
template <typename U, |
||
110 |
typename std::enable_if<!std::is_constructible<U, NoInitT, U>::value, int>::type = 0> |
||
111 |
19 |
void setHolder(NoInitT, inplace_optional_holder<U>&& value) |
|
112 |
{ |
||
113 |
19 |
m_typedHolder = std::move(value); |
|
114 |
19 |
} |
|
115 |
|||
116 |
740 |
T& get() |
|
117 |
{ |
||
118 |
740 |
return m_typedHolder.value(); |
|
119 |
} |
||
120 |
|||
121 |
48656 |
const T& get() const |
|
122 |
{ |
||
123 |
48656 |
return m_typedHolder.value(); |
|
124 |
} |
||
125 |
|||
126 |
75133 |
bool isType(detail::TypeIdHolder::type_id typeId) const override |
|
127 |
{ |
||
128 |
75133 |
return detail::TypeIdHolder::get<T>() == typeId; |
|
129 |
} |
||
130 |
|||
131 |
protected: |
||
132 |
16313 |
inplace_optional_holder<T>& getHolder() |
|
133 |
{ |
||
134 |
16313 |
return m_typedHolder; |
|
135 |
} |
||
136 |
|||
137 |
54 |
const inplace_optional_holder<T>& getHolder() const |
|
138 |
{ |
||
139 |
54 |
return m_typedHolder; |
|
140 |
} |
||
141 |
|||
142 |
private: |
||
143 |
inplace_optional_holder<T> m_typedHolder; |
||
144 |
}; |
||
145 |
|||
146 |
// Holder allocated on heap |
||
147 |
template <typename T, typename ALLOC> |
||
148 |
✗✓✗✓ ✗✓✗✓ ✗✗✗✗ ✗✓✗✗ |
16631 |
class HeapHolder : public HolderBase<T, ALLOC> |
149 |
{ |
||
150 |
private: |
||
151 |
struct ConstructTag {}; |
||
152 |
|||
153 |
public: |
||
154 |
using this_type = HeapHolder<T, ALLOC>; |
||
155 |
|||
156 |
16631 |
explicit HeapHolder(ConstructTag) noexcept {} |
|
157 |
|||
158 |
16631 |
static this_type* create(const ALLOC& allocator) |
|
159 |
{ |
||
160 |
using AllocType = RebindAlloc<ALLOC, this_type>; |
||
161 |
using AllocTraits = std::allocator_traits<AllocType>; |
||
162 |
|||
163 |
✓✗✓✗ ✓✗✓✗ |
33220 |
AllocType typedAlloc = allocator; |
164 |
✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✗✗ |
16631 |
typename AllocTraits::pointer ptr = AllocTraits::allocate(typedAlloc, 1); |
165 |
// this never throws because HeapHolder constructor never throws |
||
166 |
✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✗✗ |
16631 |
AllocTraits::construct(typedAlloc, std::addressof(*ptr), ConstructTag{}); |
167 |
33220 |
return ptr; |
|
168 |
} |
||
169 |
|||
170 |
12 |
IHolder<ALLOC>* clone(const ALLOC& allocator) const override |
|
171 |
{ |
||
172 |
12 |
this_type* holder = create(allocator); |
|
173 |
12 |
holder->setHolder(this->getHolder()); |
|
174 |
12 |
return holder; |
|
175 |
} |
||
176 |
|||
177 |
12 |
IHolder<ALLOC>* clone(NoInitT, const ALLOC& allocator) const override |
|
178 |
{ |
||
179 |
12 |
this_type* holder = create(allocator); |
|
180 |
12 |
holder->setHolder(NoInit, this->getHolder()); |
|
181 |
12 |
return holder; |
|
182 |
} |
||
183 |
|||
184 |
1 |
IHolder<ALLOC>* clone(void*) const override |
|
185 |
{ |
||
186 |
✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected clone call."); |
187 |
} |
||
188 |
|||
189 |
1 |
IHolder<ALLOC>* clone(NoInitT, void*) const override |
|
190 |
{ |
||
191 |
✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected clone call."); |
192 |
} |
||
193 |
|||
194 |
6 |
IHolder<ALLOC>* move(const ALLOC& allocator) override |
|
195 |
{ |
||
196 |
6 |
this_type* holder = create(allocator); |
|
197 |
6 |
holder->setHolder(std::move(this->getHolder())); |
|
198 |
6 |
return holder; |
|
199 |
} |
||
200 |
|||
201 |
6 |
IHolder<ALLOC>* move(NoInitT, const ALLOC& allocator) override |
|
202 |
{ |
||
203 |
6 |
this_type* holder = create(allocator); |
|
204 |
6 |
holder->setHolder(NoInit, std::move(this->getHolder())); |
|
205 |
6 |
return holder; |
|
206 |
} |
||
207 |
|||
208 |
1 |
IHolder<ALLOC>* move(void*) override |
|
209 |
{ |
||
210 |
✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected move call."); |
211 |
} |
||
212 |
|||
213 |
1 |
IHolder<ALLOC>* move(NoInitT, void*) override |
|
214 |
{ |
||
215 |
✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected move call."); |
216 |
} |
||
217 |
|||
218 |
16631 |
void destroy(const ALLOC& allocator) override |
|
219 |
{ |
||
220 |
using AllocType = RebindAlloc<ALLOC, this_type>; |
||
221 |
using AllocTraits = std::allocator_traits<AllocType>; |
||
222 |
|||
223 |
✓✗✓✗ ✓✗✓✗ |
33220 |
AllocType typedAlloc = allocator; |
224 |
✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✗✗ |
16631 |
AllocTraits::destroy(typedAlloc, this); |
225 |
✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✓✗ |
16631 |
AllocTraits::deallocate(typedAlloc, this, 1); |
226 |
16631 |
} |
|
227 |
}; |
||
228 |
|||
229 |
// Holder allocated in the in-place storage |
||
230 |
template <typename T, typename ALLOC> |
||
231 |
✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓ |
49625 |
class NonHeapHolder : public HolderBase<T, ALLOC> |
232 |
{ |
||
233 |
public: |
||
234 |
using this_type = NonHeapHolder<T, ALLOC>; |
||
235 |
|||
236 |
33294 |
static this_type* create(void* storage) |
|
237 |
{ |
||
238 |
✓✗✓✓ ✓✗✓✗ ✓✓✓✗ ✓✓✓✓ ✓✗✓✗ ✓✓✓✗ ✓✗✓✓ ✗✗✓✗ ✓✓✓✗ ✓✗✓✗ ✗✗✓✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✗✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ |
33294 |
return new (storage) this_type(); |
239 |
} |
||
240 |
|||
241 |
1 |
IHolder<ALLOC>* clone(const ALLOC&) const override |
|
242 |
{ |
||
243 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected clone call."); |
244 |
} |
||
245 |
|||
246 |
1 |
IHolder<ALLOC>* clone(NoInitT, const ALLOC&) const override |
|
247 |
{ |
||
248 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected clone call."); |
249 |
} |
||
250 |
|||
251 |
17 |
IHolder<ALLOC>* clone(void* storage) const override |
|
252 |
{ |
||
253 |
✓✗✓✓ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✓✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
17 |
NonHeapHolder* holder = new (storage) NonHeapHolder(); |
254 |
17 |
holder->setHolder(this->getHolder()); |
|
255 |
17 |
return holder; |
|
256 |
} |
||
257 |
|||
258 |
13 |
IHolder<ALLOC>* clone(NoInitT, void* storage) const override |
|
259 |
{ |
||
260 |
✗✗✗✗ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✓✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
13 |
NonHeapHolder* holder = new (storage) NonHeapHolder(); |
261 |
13 |
holder->setHolder(NoInit, this->getHolder()); |
|
262 |
13 |
return holder; |
|
263 |
} |
||
264 |
|||
265 |
1 |
IHolder<ALLOC>* move(const ALLOC&) override |
|
266 |
{ |
||
267 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected move call."); |
268 |
} |
||
269 |
|||
270 |
1 |
IHolder<ALLOC>* move(NoInitT, const ALLOC&) override |
|
271 |
{ |
||
272 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗ |
1 |
throw CppRuntimeException("AnyHolder: Unexpected move call."); |
273 |
} |
||
274 |
|||
275 |
16285 |
IHolder<ALLOC>* move(void* storage) override |
|
276 |
{ |
||
277 |
✓✗✓✓ ✓✗✓✓ ✗✗✓✗ ✗✗✗✗ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✓✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✓✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
16285 |
NonHeapHolder* holder = new (storage) NonHeapHolder(); |
278 |
16285 |
holder->setHolder(std::move(this->getHolder())); |
|
279 |
16285 |
return holder; |
|
280 |
} |
||
281 |
|||
282 |
16 |
IHolder<ALLOC>* move(NoInitT, void* storage) override |
|
283 |
{ |
||
284 |
✗✗✗✗ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✗✗✓✗ ✓✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
16 |
NonHeapHolder* holder = new (storage) NonHeapHolder(); |
285 |
16 |
holder->setHolder(NoInit, std::move(this->getHolder())); |
|
286 |
16 |
return holder; |
|
287 |
} |
||
288 |
|||
289 |
49625 |
void destroy(const ALLOC&) override |
|
290 |
{ |
||
291 |
49625 |
this->~NonHeapHolder(); |
|
292 |
49625 |
} |
|
293 |
|||
294 |
private: |
||
295 |
49625 |
NonHeapHolder() = default; |
|
296 |
}; |
||
297 |
|||
298 |
template <typename ALLOC> |
||
299 |
union UntypedHolder |
||
300 |
{ |
||
301 |
// 2 * sizeof(void*) for T + sizeof(void*) for Holder's vptr |
||
302 |
using MaxInPlaceType = std::aligned_storage<3 * sizeof(void*), alignof(void*)>::type; |
||
303 |
|||
304 |
detail::IHolder<ALLOC>* heap; |
||
305 |
MaxInPlaceType inPlace; |
||
306 |
}; |
||
307 |
|||
308 |
template <typename T, typename ALLOC> |
||
309 |
using has_non_heap_holder = std::integral_constant<bool, |
||
310 |
sizeof(NonHeapHolder<T, ALLOC>) <= sizeof(typename UntypedHolder<ALLOC>::MaxInPlaceType) && |
||
311 |
std::is_nothrow_move_constructible<T>::value && |
||
312 |
alignof(T) <= alignof(typename UntypedHolder<ALLOC>::MaxInPlaceType)>; |
||
313 |
} // namespace detail |
||
314 |
|||
315 |
/** |
||
316 |
* Type safe container for single values of any type which doesn't need RTTI. |
||
317 |
*/ |
||
318 |
template <typename ALLOC = std::allocator<uint8_t>> |
||
319 |
class AnyHolder : public AllocatorHolder<ALLOC> |
||
320 |
{ |
||
321 |
using AllocTraits = std::allocator_traits<ALLOC>; |
||
322 |
using AllocatorHolder<ALLOC>::get_allocator_ref; |
||
323 |
using AllocatorHolder<ALLOC>::set_allocator; |
||
324 |
|||
325 |
public: |
||
326 |
using AllocatorHolder<ALLOC>::get_allocator; |
||
327 |
using allocator_type = ALLOC; |
||
328 |
|||
329 |
/** |
||
330 |
* Empty constructor. |
||
331 |
*/ |
||
332 |
✓✗✓✗ |
375 |
AnyHolder() : AnyHolder(ALLOC()) |
333 |
{ |
||
334 |
375 |
} |
|
335 |
|||
336 |
/** |
||
337 |
* Constructor from given allocator |
||
338 |
*/ |
||
339 |
944 |
explicit AnyHolder(const ALLOC& allocator) : |
|
340 |
944 |
AllocatorHolder<ALLOC>(allocator) |
|
341 |
{ |
||
342 |
944 |
m_untypedHolder.heap = nullptr; |
|
343 |
944 |
} |
|
344 |
|||
345 |
/** |
||
346 |
* Constructor from any value. |
||
347 |
* |
||
348 |
* \param value Value of any type to hold. Supports move semantic. |
||
349 |
*/ |
||
350 |
template <typename T, |
||
351 |
typename std::enable_if<!std::is_same<typename std::decay<T>::type, AnyHolder>::value && |
||
352 |
!std::is_same<typename std::decay<T>::type, ALLOC>::value, int>::type = 0> |
||
353 |
25140 |
explicit AnyHolder(T&& value, const ALLOC& allocator = ALLOC()) : |
|
354 |
25140 |
AllocatorHolder<ALLOC>(allocator) |
|
355 |
{ |
||
356 |
25140 |
m_untypedHolder.heap = nullptr; |
|
357 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✗✗ ✗✗✓✗ ✗✗✓✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✓✗ ✓✗✗✗ ✗✗✗✗ ✓✗✗✗ |
25140 |
set(std::forward<T>(value)); |
358 |
25140 |
} |
|
359 |
|||
360 |
/** |
||
361 |
* Constructor from any value which prevents initialization. |
||
362 |
* |
||
363 |
* \param value Value of any type to hold. Supports move semantic. |
||
364 |
*/ |
||
365 |
template <typename T, typename std::enable_if< |
||
366 |
!std::is_same<typename std::decay<T>::type, AnyHolder>::value, int>::type = 0> |
||
367 |
18 |
explicit AnyHolder(NoInitT, T&& value, const ALLOC& allocator = ALLOC()) : |
|
368 |
18 |
AllocatorHolder<ALLOC>(allocator) |
|
369 |
{ |
||
370 |
18 |
m_untypedHolder.heap = nullptr; |
|
371 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
18 |
set(NoInit, std::forward<T>(value)); |
372 |
18 |
} |
|
373 |
|||
374 |
/** |
||
375 |
* Destructor. |
||
376 |
*/ |
||
377 |
26310 |
~AnyHolder() |
|
378 |
{ |
||
379 |
26310 |
clearHolder(); |
|
380 |
26310 |
} |
|
381 |
|||
382 |
/** |
||
383 |
* Copy constructor. |
||
384 |
* |
||
385 |
* \param other Any holder to copy. |
||
386 |
*/ |
||
387 |
29 |
AnyHolder(const AnyHolder& other) : |
|
388 |
AllocatorHolder<ALLOC>( |
||
389 |
29 |
AllocTraits::select_on_container_copy_construction(other.get_allocator_ref())) |
|
390 |
{ |
||
391 |
✓✗✗✓ ✗ |
29 |
copy(other); |
392 |
29 |
} |
|
393 |
|||
394 |
/** |
||
395 |
* Copy constructor which prevents initialization. |
||
396 |
* |
||
397 |
* \param other Any holder to copy. |
||
398 |
*/ |
||
399 |
24 |
AnyHolder(NoInitT, const AnyHolder& other) : |
|
400 |
AllocatorHolder<ALLOC>( |
||
401 |
24 |
AllocTraits::select_on_container_copy_construction(other.get_allocator_ref())) |
|
402 |
{ |
||
403 |
✓✗✓✗ |
24 |
copy(NoInit, other); |
404 |
24 |
} |
|
405 |
|||
406 |
/** |
||
407 |
* Allocator-extended copy constructor. |
||
408 |
* |
||
409 |
* \param other Any holder to copy. |
||
410 |
* \param allocator Allocator to be used for dynamic memory allocations. |
||
411 |
*/ |
||
412 |
8 |
AnyHolder(const AnyHolder& other, const ALLOC& allocator) : AllocatorHolder<ALLOC>(allocator) |
|
413 |
{ |
||
414 |
✓✗✓✗ |
8 |
copy(other); |
415 |
8 |
} |
|
416 |
|||
417 |
/** |
||
418 |
* Allocator-extended copy constructor which prevents initialization. |
||
419 |
* |
||
420 |
* \param other Any holder to copy. |
||
421 |
* \param allocator Allocator to be used for dynamic memory allocations. |
||
422 |
*/ |
||
423 |
8 |
AnyHolder(NoInitT, const AnyHolder& other, const ALLOC& allocator) : |
|
424 |
8 |
AllocatorHolder<ALLOC>(allocator) |
|
425 |
{ |
||
426 |
✓✗✓✗ |
8 |
copy(NoInit, other); |
427 |
8 |
} |
|
428 |
|||
429 |
/** |
||
430 |
* Copy assignment operator. |
||
431 |
* |
||
432 |
* \param other Any holder to copy. |
||
433 |
* |
||
434 |
* \return Reference to this. |
||
435 |
*/ |
||
436 |
24 |
AnyHolder& operator=(const AnyHolder& other) |
|
437 |
{ |
||
438 |
✓✓✓✓ |
24 |
if (this != &other) |
439 |
{ |
||
440 |
// TODO: do not dealloc unless necessary |
||
441 |
16 |
clearHolder(); |
|
442 |
if (AllocTraits::propagate_on_container_copy_assignment::value) |
||
443 |
8 |
set_allocator(other.get_allocator_ref()); |
|
444 |
16 |
copy(other); |
|
445 |
} |
||
446 |
|||
447 |
24 |
return *this; |
|
448 |
} |
||
449 |
|||
450 |
/** |
||
451 |
* Copy assignment operator which prevents initialization. |
||
452 |
* |
||
453 |
* \param other Any holder to copy. |
||
454 |
* |
||
455 |
* \return Reference to this. |
||
456 |
*/ |
||
457 |
37 |
AnyHolder& assign(NoInitT, const AnyHolder& other) |
|
458 |
{ |
||
459 |
✓✓✓✓ |
37 |
if (this != &other) |
460 |
{ |
||
461 |
// TODO: do not dealloc unless necessary |
||
462 |
29 |
clearHolder(); |
|
463 |
if (AllocTraits::propagate_on_container_copy_assignment::value) |
||
464 |
8 |
set_allocator(other.get_allocator_ref()); |
|
465 |
29 |
copy(NoInit, other); |
|
466 |
} |
||
467 |
|||
468 |
37 |
return *this; |
|
469 |
} |
||
470 |
|||
471 |
/** |
||
472 |
* Move constructor. |
||
473 |
* |
||
474 |
* \param other Any holder to move from. |
||
475 |
*/ |
||
476 |
62 |
AnyHolder(AnyHolder&& other) noexcept : |
|
477 |
62 |
AllocatorHolder<ALLOC>(std::move(other.get_allocator_ref())) |
|
478 |
{ |
||
479 |
62 |
move(std::move(other)); |
|
480 |
62 |
} |
|
481 |
|||
482 |
/** |
||
483 |
* Move constructor which prevents initialization. |
||
484 |
* |
||
485 |
* \param other Any holder to move from. |
||
486 |
*/ |
||
487 |
29 |
AnyHolder(NoInitT, AnyHolder&& other) noexcept : |
|
488 |
29 |
AllocatorHolder<ALLOC>(std::move(other.get_allocator_ref())) |
|
489 |
{ |
||
490 |
29 |
move(NoInit, std::move(other)); |
|
491 |
29 |
} |
|
492 |
|||
493 |
/** |
||
494 |
* Allocator-extended move constructor. |
||
495 |
* |
||
496 |
* \param other Any holder to move from. |
||
497 |
* \param allocator Allocator to be used for dynamic memory allocations. |
||
498 |
*/ |
||
499 |
24 |
AnyHolder(AnyHolder&& other, const ALLOC& allocator) : |
|
500 |
24 |
AllocatorHolder<ALLOC>(allocator) |
|
501 |
{ |
||
502 |
✓✗✓✗ |
24 |
move(std::move(other)); |
503 |
24 |
} |
|
504 |
|||
505 |
/** |
||
506 |
* Allocator-extended move constructor which prevents initialization. |
||
507 |
* |
||
508 |
* \param other Any holder to move from. |
||
509 |
* \param allocator Allocator to be used for dynamic memory allocations. |
||
510 |
*/ |
||
511 |
24 |
AnyHolder(NoInitT, AnyHolder&& other, const ALLOC& allocator) : |
|
512 |
24 |
AllocatorHolder<ALLOC>(allocator) |
|
513 |
{ |
||
514 |
✓✗✓✗ |
24 |
move(NoInit, std::move(other)); |
515 |
24 |
} |
|
516 |
|||
517 |
/** |
||
518 |
* Move assignment operator. |
||
519 |
* |
||
520 |
* \param other Any holder to move from. |
||
521 |
* |
||
522 |
* \return Reference to this. |
||
523 |
*/ |
||
524 |
48888 |
AnyHolder& operator=(AnyHolder&& other) |
|
525 |
{ |
||
526 |
✓✓✓✓ |
48888 |
if (this != &other) |
527 |
{ |
||
528 |
48880 |
clearHolder(); |
|
529 |
if (AllocTraits::propagate_on_container_move_assignment::value) |
||
530 |
48872 |
set_allocator(std::move(other.get_allocator_ref())); |
|
531 |
48880 |
move(std::move(other)); |
|
532 |
} |
||
533 |
|||
534 |
48888 |
return *this; |
|
535 |
} |
||
536 |
|||
537 |
/** |
||
538 |
* Move assignment operator which prevents initialization. |
||
539 |
* |
||
540 |
* \param other Any holder to move from. |
||
541 |
* |
||
542 |
* \return Reference to this. |
||
543 |
*/ |
||
544 |
27 |
AnyHolder& assign(NoInitT, AnyHolder&& other) |
|
545 |
{ |
||
546 |
✓✓✓✓ |
27 |
if (this != &other) |
547 |
{ |
||
548 |
19 |
clearHolder(); |
|
549 |
if (AllocTraits::propagate_on_container_move_assignment::value) |
||
550 |
11 |
set_allocator(std::move(other.get_allocator_ref())); |
|
551 |
19 |
move(NoInit, std::move(other)); |
|
552 |
} |
||
553 |
|||
554 |
27 |
return *this; |
|
555 |
} |
||
556 |
|||
557 |
/** |
||
558 |
* Value assignment operator. |
||
559 |
* |
||
560 |
* \param value Any value to assign. Supports move semantic. |
||
561 |
* |
||
562 |
* \return Reference to this. |
||
563 |
*/ |
||
564 |
template <typename T, typename |
||
565 |
std::enable_if<!std::is_same<typename std::decay<T>::type, AnyHolder>::value, int>::type = 0> |
||
566 |
72 |
AnyHolder& operator=(T&& value) |
|
567 |
{ |
||
568 |
72 |
set(std::forward<T>(value)); |
|
569 |
|||
570 |
72 |
return *this; |
|
571 |
} |
||
572 |
|||
573 |
/** |
||
574 |
* Resets the holder. |
||
575 |
*/ |
||
576 |
66 |
void reset() |
|
577 |
{ |
||
578 |
66 |
clearHolder(); |
|
579 |
66 |
} |
|
580 |
|||
581 |
/** |
||
582 |
* Sets any value to the holder. |
||
583 |
* |
||
584 |
* \param value Any value to set. Supports move semantic. |
||
585 |
*/ |
||
586 |
template <typename T> |
||
587 |
50057 |
void set(T&& value) |
|
588 |
{ |
||
589 |
50057 |
createHolder<typename std::decay<T>::type>()->set(std::forward<T>(value)); |
|
590 |
50057 |
} |
|
591 |
|||
592 |
/** |
||
593 |
* Sets any value to the holder and prevent initialization. |
||
594 |
* |
||
595 |
* \param value Any value to set. Supports move semantic. |
||
596 |
*/ |
||
597 |
template <typename T> |
||
598 |
18 |
void set(NoInitT, T&& value) |
|
599 |
{ |
||
600 |
18 |
createHolder<typename std::decay<T>::type>()->set(NoInit, std::forward<T>(value)); |
|
601 |
18 |
} |
|
602 |
|||
603 |
/** |
||
604 |
* Gets value of the given type. |
||
605 |
* |
||
606 |
* \return Reference to value of the requested type if the type match to the stored value. |
||
607 |
* |
||
608 |
* \throw CppRuntimeException if the requested type doesn't match to the stored value. |
||
609 |
*/ |
||
610 |
template <typename T> |
||
611 |
772 |
T& get() |
|
612 |
{ |
||
613 |
772 |
checkType<T>(); |
|
614 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
740 |
return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>())->get(); |
615 |
} |
||
616 |
|||
617 |
/** |
||
618 |
* Gets value of the given type. |
||
619 |
* |
||
620 |
* \return Value of the requested type if the type match to the stored value. |
||
621 |
* |
||
622 |
* \throw CppRuntimeException if the requested type doesn't match to the stored value. |
||
623 |
*/ |
||
624 |
template <typename T> |
||
625 |
48657 |
const T& get() const |
|
626 |
{ |
||
627 |
48657 |
checkType<T>(); |
|
628 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✓✗✓✗ ✓✗✓✗ |
48656 |
return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>())->get(); |
629 |
} |
||
630 |
|||
631 |
/** |
||
632 |
* Check whether the holder holds the given type. |
||
633 |
* |
||
634 |
* \return True if the stored value is of the given type, false otherwise. |
||
635 |
*/ |
||
636 |
template <typename T> |
||
637 |
50549 |
bool isType() const |
|
638 |
{ |
||
639 |
✓✗✓✓ ✓✗✓✗ ✓✗✓✓ ✓✗✓✗ ✓✗✓✓ ✓✗✓✗ ✓✗✓✓ ✓✓✓✓ ✓✗✓✓ ✓✓✓✓ ✓✗✓✓ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✗ ✗✗✗✗ ✗✗✗✗ ✓✗✓✓ ✓✗✓✓ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ |
50549 |
return hasHolder() && getUntypedHolder()->isType(detail::TypeIdHolder::get<T>()); |
640 |
} |
||
641 |
|||
642 |
/** |
||
643 |
* Checks whether the holder has any value. |
||
644 |
* |
||
645 |
* \return True if the holder has assigned any value, false otherwise. |
||
646 |
*/ |
||
647 |
24684 |
bool hasValue() const |
|
648 |
{ |
||
649 |
24684 |
return hasHolder(); |
|
650 |
} |
||
651 |
|||
652 |
private: |
||
653 |
53 |
void copy(const AnyHolder& other) |
|
654 |
{ |
||
655 |
✓✓✓✓ |
53 |
if (other.m_isInPlace) |
656 |
{ |
||
657 |
17 |
other.getUntypedHolder()->clone(&m_untypedHolder.inPlace); |
|
658 |
17 |
m_isInPlace = true; |
|
659 |
} |
||
660 |
✓✓✓✓ |
36 |
else if (other.m_untypedHolder.heap != nullptr) |
661 |
{ |
||
662 |
12 |
m_untypedHolder.heap = other.getUntypedHolder()->clone(get_allocator_ref()); |
|
663 |
} |
||
664 |
else |
||
665 |
{ |
||
666 |
24 |
m_untypedHolder.heap = nullptr; |
|
667 |
} |
||
668 |
53 |
} |
|
669 |
|||
670 |
61 |
void copy(NoInitT, const AnyHolder& other) |
|
671 |
{ |
||
672 |
✓✓✓✓ |
61 |
if (other.m_isInPlace) |
673 |
{ |
||
674 |
13 |
other.getUntypedHolder()->clone(NoInit, &m_untypedHolder.inPlace); |
|
675 |
13 |
m_isInPlace = true; |
|
676 |
} |
||
677 |
✓✓✓✓ |
48 |
else if (other.m_untypedHolder.heap != nullptr) |
678 |
{ |
||
679 |
24 |
m_untypedHolder.heap = other.getUntypedHolder()->clone(NoInit, |
|
680 |
12 |
get_allocator_ref()); |
|
681 |
} |
||
682 |
else |
||
683 |
{ |
||
684 |
36 |
m_untypedHolder.heap = nullptr; |
|
685 |
} |
||
686 |
61 |
} |
|
687 |
|||
688 |
48966 |
void move(AnyHolder&& other) |
|
689 |
{ |
||
690 |
✓✓✓✓ |
48966 |
if (other.m_isInPlace) |
691 |
{ |
||
692 |
16285 |
other.getUntypedHolder()->move(&m_untypedHolder.inPlace); |
|
693 |
16285 |
m_isInPlace = true; |
|
694 |
16285 |
other.clearHolder(); |
|
695 |
} |
||
696 |
✓✓✓✓ |
32681 |
else if (other.m_untypedHolder.heap != nullptr) |
697 |
{ |
||
698 |
✓✓✓✓ |
32645 |
if (get_allocator_ref() == other.get_allocator_ref()) |
699 |
{ |
||
700 |
// take over the other's storage |
||
701 |
32639 |
m_untypedHolder.heap = other.m_untypedHolder.heap; |
|
702 |
32639 |
other.m_untypedHolder.heap = nullptr; |
|
703 |
} |
||
704 |
else |
||
705 |
{ |
||
706 |
// cannot steal the storage, allocate our own and move the holder |
||
707 |
6 |
m_untypedHolder.heap = other.getUntypedHolder()->move(get_allocator_ref()); |
|
708 |
6 |
other.clearHolder(); |
|
709 |
} |
||
710 |
} |
||
711 |
else |
||
712 |
{ |
||
713 |
36 |
m_untypedHolder.heap = nullptr; |
|
714 |
} |
||
715 |
48966 |
} |
|
716 |
|||
717 |
72 |
void move(NoInitT, AnyHolder&& other) |
|
718 |
{ |
||
719 |
✓✓✓✓ |
72 |
if (other.m_isInPlace) |
720 |
{ |
||
721 |
16 |
other.getUntypedHolder()->move(NoInit, &m_untypedHolder.inPlace); |
|
722 |
16 |
m_isInPlace = true; |
|
723 |
16 |
other.clearHolder(); |
|
724 |
} |
||
725 |
✓✓✓✓ |
56 |
else if (other.m_untypedHolder.heap != nullptr) |
726 |
{ |
||
727 |
✓✓✓✓ |
17 |
if (get_allocator_ref() == other.get_allocator_ref()) |
728 |
{ |
||
729 |
// take over the other's storage |
||
730 |
11 |
m_untypedHolder.heap = other.m_untypedHolder.heap; |
|
731 |
11 |
other.m_untypedHolder.heap = nullptr; |
|
732 |
} |
||
733 |
else |
||
734 |
{ |
||
735 |
// cannot steal the storage, allocate our own and move the holder |
||
736 |
12 |
m_untypedHolder.heap = other.getUntypedHolder()->move(NoInit, |
|
737 |
6 |
get_allocator_ref()); |
|
738 |
6 |
other.clearHolder(); |
|
739 |
} |
||
740 |
} |
||
741 |
else |
||
742 |
{ |
||
743 |
39 |
m_untypedHolder.heap = nullptr; |
|
744 |
} |
||
745 |
72 |
} |
|
746 |
|||
747 |
116045 |
void clearHolder() |
|
748 |
{ |
||
749 |
✓✓✓✓ |
116045 |
if (hasHolder()) |
750 |
{ |
||
751 |
66254 |
getUntypedHolder()->destroy(get_allocator_ref()); |
|
752 |
66254 |
m_isInPlace = false; |
|
753 |
66254 |
m_untypedHolder.heap = nullptr; |
|
754 |
} |
||
755 |
116045 |
} |
|
756 |
|||
757 |
241353 |
bool hasHolder() const |
|
758 |
{ |
||
759 |
✓✓✓✓ ✓✓✓✓ |
241353 |
return (m_isInPlace || m_untypedHolder.heap != nullptr); |
760 |
} |
||
761 |
|||
762 |
template <typename T> |
||
763 |
50075 |
detail::HolderBase<T, ALLOC>* createHolder() |
|
764 |
{ |
||
765 |
✗✓✗✓ ✗✓✗✓ ✓✓✓✓ ✓✓✓✓ ✓✓✓✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✗✗✓ ✓✓✓✓ ✗✓✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✗✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ |
50075 |
if (hasHolder()) |
766 |
{ |
||
767 |
✗✗✗✗ ✗✗✗✗ ✗✓✗✓ ✓✓✗✓ ✗✓✓✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✓✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
24600 |
if (getUntypedHolder()->isType(detail::TypeIdHolder::get<T>())) |
768 |
✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ |
188 |
return getHolder<T>(detail::has_non_heap_holder<T, ALLOC>()); |
769 |
|||
770 |
24412 |
clearHolder(); |
|
771 |
} |
||
772 |
|||
773 |
✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✓✗ ✓✗✓✗ ✓✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✗✓✗ ✓✗✓✗ ✓✗✓✗ ✓✗✓✗ ✗✗✓✗ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✓✗✗✗ |
49887 |
return createHolderImpl<T>(detail::has_non_heap_holder<T, ALLOC>()); |
774 |
} |
||
775 |
|||
776 |
template <typename T> |
||
777 |
33293 |
detail::HolderBase<T, ALLOC>* createHolderImpl(std::true_type) |
|
778 |
{ |
||
779 |
detail::NonHeapHolder<T, ALLOC>* holder = |
||
780 |
33293 |
detail::NonHeapHolder<T, ALLOC>::create(&m_untypedHolder.inPlace); |
|
781 |
33293 |
m_isInPlace = true; |
|
782 |
33293 |
return holder; |
|
783 |
} |
||
784 |
|||
785 |
template <typename T> |
||
786 |
16594 |
detail::HolderBase<T, ALLOC>* createHolderImpl(std::false_type) |
|
787 |
{ |
||
788 |
16594 |
detail::HeapHolder<T, ALLOC>* holder = detail::HeapHolder<T, ALLOC>::create(get_allocator_ref()); |
|
789 |
16594 |
m_untypedHolder.heap = holder; |
|
790 |
16594 |
return holder; |
|
791 |
} |
||
792 |
|||
793 |
template <typename T> |
||
794 |
49429 |
void checkType() const |
|
795 |
{ |
||
796 |
✗✓✗✓ ✗✓✗✓ ✗✓✓✓ ✓✓✗✓ ✓✓✓✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✗✗✗ ✗✗✗✗ ✗✗✗✗ ✗✓✗✗ ✗✗✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ ✗✓✗✓ |
49429 |
if (!isType<T>()) |
797 |
33 |
throwBadType(); |
|
798 |
49396 |
} |
|
799 |
|||
800 |
/** Optimization which increases changes to inline checkType(). */ |
||
801 |
33 |
void throwBadType() const |
|
802 |
{ |
||
803 |
✓✗✓✗ |
33 |
throw CppRuntimeException("Bad type in AnyHolder"); |
804 |
} |
||
805 |
|||
806 |
template <typename T> |
||
807 |
168 |
detail::HeapHolder<T, ALLOC>* getHeapHolder() |
|
808 |
{ |
||
809 |
168 |
return static_cast<detail::HeapHolder<T, ALLOC>*>(m_untypedHolder.heap); |
|
810 |
} |
||
811 |
|||
812 |
template <typename T> |
||
813 |
16414 |
const detail::HeapHolder<T, ALLOC>* getHeapHolder() const |
|
814 |
{ |
||
815 |
16414 |
return static_cast<detail::HeapHolder<T, ALLOC>*>(m_untypedHolder.heap); |
|
816 |
} |
||
817 |
|||
818 |
template <typename T> |
||
819 |
760 |
detail::NonHeapHolder<T, ALLOC>* getInplaceHolder() |
|
820 |
{ |
||
821 |
760 |
return reinterpret_cast<detail::NonHeapHolder<T, ALLOC>*>(&m_untypedHolder.inPlace); |
|
822 |
} |
||
823 |
|||
824 |
template <typename T> |
||
825 |
32242 |
const detail::NonHeapHolder<T, ALLOC>* getInplaceHolder() const |
|
826 |
{ |
||
827 |
32242 |
return reinterpret_cast<const detail::NonHeapHolder<T, ALLOC>*>(&m_untypedHolder.inPlace); |
|
828 |
} |
||
829 |
|||
830 |
template <typename T> |
||
831 |
760 |
detail::HolderBase<T, ALLOC>* getHolder(std::true_type) |
|
832 |
{ |
||
833 |
760 |
return static_cast<detail::HolderBase<T, ALLOC>*>(getInplaceHolder<T>()); |
|
834 |
} |
||
835 |
|||
836 |
template <typename T> |
||
837 |
168 |
detail::HolderBase<T, ALLOC>* getHolder(std::false_type) |
|
838 |
{ |
||
839 |
168 |
return static_cast<detail::HolderBase<T, ALLOC>*>(getHeapHolder<T>()); |
|
840 |
} |
||
841 |
|||
842 |
template <typename T> |
||
843 |
32242 |
const detail::HolderBase<T, ALLOC>* getHolder(std::true_type) const |
|
844 |
{ |
||
845 |
32242 |
return static_cast<const detail::HolderBase<T, ALLOC>*>(getInplaceHolder<T>()); |
|
846 |
} |
||
847 |
|||
848 |
template <typename T> |
||
849 |
16414 |
const detail::HolderBase<T, ALLOC>* getHolder(std::false_type) const |
|
850 |
{ |
||
851 |
16414 |
return static_cast<const detail::HolderBase<T, ALLOC>*>(getHeapHolder<T>()); |
|
852 |
} |
||
853 |
|||
854 |
107167 |
detail::IHolder<ALLOC>* getUntypedHolder() |
|
855 |
{ |
||
856 |
107167 |
return (m_isInPlace) ? |
|
857 |
reinterpret_cast<detail::IHolder<ALLOC>*>(&m_untypedHolder.inPlace) : |
||
858 |
✓✓✓✓ |
107167 |
m_untypedHolder.heap; |
859 |
} |
||
860 |
|||
861 |
50587 |
const detail::IHolder<ALLOC>* getUntypedHolder() const |
|
862 |
{ |
||
863 |
50587 |
return (m_isInPlace) ? |
|
864 |
reinterpret_cast<const detail::IHolder<ALLOC>*>(&m_untypedHolder.inPlace) : |
||
865 |
✓✓✓✓ |
50587 |
m_untypedHolder.heap; |
866 |
} |
||
867 |
|||
868 |
detail::UntypedHolder<ALLOC> m_untypedHolder; |
||
869 |
bool m_isInPlace = false; |
||
870 |
}; |
||
871 |
|||
872 |
} // namespace zserio |
||
873 |
|||
874 |
#endif // ifndef ZSERIO_ANY_HOLDER_H_INC |
Generated by: GCOVR (Version 4.2) |