Lely core libraries 2.3.4
c_type.hpp
Go to the documentation of this file.
1
22#ifndef LELY_UTIL_C_TYPE_HPP_
23#define LELY_UTIL_C_TYPE_HPP_
24
26
27#include <algorithm>
28#include <memory>
29#include <new>
30#include <utility>
31
32namespace lely {
33
38class bad_init : public error {};
39
44class bad_copy : public error {};
45
50class bad_move : public error {};
51
52namespace impl {
53
54inline void
55throw_bad_init() {
56 if (get_errnum() == ERRNUM_NOMEM) throw_or_abort(::std::bad_alloc());
58}
59
60inline void
61throw_bad_copy() {
62 if (get_errnum() == ERRNUM_NOMEM) throw_or_abort(::std::bad_alloc());
63 throw_or_abort(bad_copy());
64}
65
66inline void
67throw_bad_move() {
68 if (get_errnum() == ERRNUM_NOMEM) throw_or_abort(::std::bad_alloc());
69 throw_or_abort(bad_move());
70}
71
72} // namespace impl
73
75template <class T>
77 constexpr delete_c_type() noexcept = default;
78 template <class U>
79 delete_c_type(const delete_c_type<U>&) noexcept {}
80
81 void
82 operator()(T* p) const {
83 destroy(p);
84 }
85};
86
91template <class T, class... Args>
92inline ::std::shared_ptr<T>
94 return ::std::shared_ptr<T>(new T(::std::forward<Args>(args)...),
96}
97
102template <class T>
103using unique_c_ptr = ::std::unique_ptr<T, delete_c_type<T>>;
104
109template <class T, class... Args>
110inline unique_c_ptr<T>
112 return unique_c_ptr<T>(new T(::std::forward<Args>(args)...));
113}
114
119template <class T>
120struct c_type_traits;
121
123template <class T>
125 typedef typename c_type_traits<T>::value_type c_value_type;
126 typedef typename c_type_traits<T>::reference c_reference;
127 typedef typename c_type_traits<T>::const_reference c_const_reference;
128 typedef typename c_type_traits<T>::pointer c_pointer;
129 typedef typename c_type_traits<T>::const_pointer c_const_pointer;
130
131 operator c_value_type() const noexcept { return c_ref(); }
132 operator c_reference() noexcept { return c_ref(); }
133 operator c_const_reference() const noexcept { return c_ref(); }
134
135 c_reference
136 c_ref() noexcept {
137 return *c_ptr();
138 }
139
140 c_const_reference
141 c_ref() const noexcept {
142 return *c_ptr();
143 }
144
145 c_pointer
146 c_ptr() noexcept {
147 return reinterpret_cast<c_pointer>(this);
148 }
149
150 c_const_pointer
151 c_ptr() const noexcept {
152 return reinterpret_cast<c_const_pointer>(this);
153 }
154
155 static void
156 dtor(trivial_c_type* p) noexcept {
157 delete p;
158 }
159
160 void
161 destroy() noexcept {
162 dtor(this);
163 }
164};
165
166template <class T>
167inline void
168destroy(trivial_c_type<T>* p) noexcept {
169 p->destroy();
170}
171
173template <class T>
175 public:
176 typedef typename c_type_traits<T>::value_type c_value_type;
177 typedef typename c_type_traits<T>::reference c_reference;
178 typedef typename c_type_traits<T>::const_reference c_const_reference;
179 typedef typename c_type_traits<T>::pointer c_pointer;
180 typedef typename c_type_traits<T>::const_pointer c_const_pointer;
181
182 operator c_value_type() const noexcept { return c_ref(); }
183 operator c_reference() noexcept { return c_ref(); }
184 operator c_const_reference() const noexcept { return c_ref(); }
185
186 c_reference
187 c_ref() noexcept {
188 return *c_ptr();
189 }
190
191 c_const_reference
192 c_ref() const noexcept {
193 return *c_ptr();
194 }
195
196 c_pointer
197 c_ptr() noexcept {
198 return reinterpret_cast<c_pointer>(this);
199 }
200
201 c_const_pointer
202 c_ptr() const noexcept {
203 return reinterpret_cast<c_const_pointer>(this);
204 }
205
206 static void
207 dtor(standard_c_type* p) noexcept {
208 delete p;
209 }
210
211 void
212 destroy() noexcept {
213 dtor(this);
214 }
215
217 operator=(const standard_c_type& val) {
218 if (!c_type_traits<T>::copy(c_ptr(), val.c_ptr())) impl::throw_bad_copy();
219 return *this;
220 }
221
223 operator=(standard_c_type&& val) {
224 if (!c_type_traits<T>::move(c_ptr(), val.c_ptr())) impl::throw_bad_move();
225 return *this;
226 }
227
228 protected:
229 template <class... Args>
230 explicit standard_c_type(Args&&... args) {
231 if (!c_type_traits<T>::init(c_ptr(), std::forward<Args>(args)...))
232 impl::throw_bad_init();
233 }
234
236};
237
238template <class T>
239inline void
240destroy(standard_c_type<T>* p) noexcept {
241 p->destroy();
242}
243
248template <class T>
250 public:
251 typedef typename c_type_traits<T>::value_type c_value_type;
252 typedef typename c_type_traits<T>::reference c_reference;
253 typedef typename c_type_traits<T>::const_reference c_const_reference;
254 typedef typename c_type_traits<T>::pointer c_pointer;
255 typedef typename c_type_traits<T>::const_pointer c_const_pointer;
256
257 operator c_reference() noexcept { return c_ref(); }
258 operator c_const_reference() const noexcept { return c_ref(); }
259
260 c_reference
261 c_ref() noexcept {
262 return *c_ptr();
263 }
264
265 c_const_reference
266 c_ref() const noexcept {
267 return *c_ptr();
268 }
269
270 c_pointer
271 c_ptr() noexcept {
272 return reinterpret_cast<c_pointer>(this);
273 }
274
275 c_const_pointer
276 c_ptr() const noexcept {
277 return reinterpret_cast<c_const_pointer>(this);
278 }
279
280 static void
281 dtor(incomplete_c_type* p) noexcept {
282 delete p;
283 }
284
285 void
286 destroy() noexcept {
287 dtor(this);
288 }
289
290 void*
291 operator new(std::size_t size) {
292 void* ptr = operator new(size, ::std::nothrow);
293 if (!ptr) throw_or_abort(std::bad_alloc());
294 return ptr;
295 }
296
297 void*
298 operator new(std::size_t, const ::std::nothrow_t&) noexcept {
300 }
301
302 void
303 operator delete(void* ptr) noexcept {
304 operator delete(ptr, ::std::nothrow);
305 }
306
307 void
308 operator delete(void* ptr, const ::std::nothrow_t&) noexcept {
310 }
311
313 operator=(const incomplete_c_type& val) {
314 if (!c_type_traits<T>::copy(c_ptr(), val.c_ptr())) impl::throw_bad_copy();
315 return *this;
316 }
317
319 operator=(incomplete_c_type&& val) {
320 if (!c_type_traits<T>::move(c_ptr(), val.c_ptr())) impl::throw_bad_move();
321 return *this;
322 }
323
324 void* operator new[](std::size_t) = delete;
325 void* operator new[](std::size_t, const ::std::nothrow_t&) = delete;
326 void operator delete[](void*) = delete;
327 void operator delete[](void*, const ::std::nothrow_t&) = delete;
328
329 protected:
330 template <class... Args>
331 explicit incomplete_c_type(Args&&... args) {
332 if (!c_type_traits<T>::init(c_ptr(), ::std::forward<Args>(args)...))
333 impl::throw_bad_init();
334 }
335
337};
338
339template <class T>
340inline void
341destroy(incomplete_c_type<T>* p) noexcept {
342 p->destroy();
343}
344
349template <class T>
351 typedef T value_type;
352 typedef value_type& reference;
353 typedef const value_type& const_reference;
354 typedef value_type* pointer;
355 typedef const value_type* const_pointer;
356
357 static void*
358 alloc() noexcept {
359 return operator new(sizeof(T), ::std::nothrow);
360 }
361
362 static void
363 free(void* ptr) noexcept {
364 operator delete(ptr, ::std::nothrow);
365 }
366
367 static pointer
368 init(pointer p) noexcept {
369 return p;
370 }
371
372 static pointer
373 init(pointer p, const T& val) noexcept {
374 return new (static_cast<void*>(p)) T(val);
375 }
376
377 static void
378 fini(pointer p) noexcept {
379 p->~T();
380 }
381
382 static pointer
383 copy(pointer p1, const_pointer p2) noexcept {
384 *p1 = *p2;
385 return p1;
386 }
387
388 static pointer
389 move(pointer p1, pointer p2) noexcept {
390 *p1 = ::std::move(*p2);
391 return p1;
392 }
393};
394
399template <>
401 typedef void value_type;
402 typedef struct {
403 } __type;
404 typedef __type& reference;
405 typedef const __type& const_reference;
406 typedef value_type* pointer;
407 typedef const value_type* const_pointer;
408
409 static void*
410 alloc() noexcept {
411 return operator new(0, ::std::nothrow);
412 }
413
414 static void
415 free(void* ptr) noexcept {
416 operator delete(ptr, ::std::nothrow);
417 }
418
419 static pointer
420 init(pointer p) noexcept {
421 return p;
422 }
423
424 static void
425 fini(pointer p) noexcept {
426 (void)p;
427 }
428
429 static pointer
430 copy(pointer p1, const_pointer p2) noexcept {
431 (void)p2;
432
433 return p1;
434 }
435
436 static pointer
437 move(pointer p1, pointer p2) noexcept {
438 (void)p2;
439
440 return p1;
441 }
442};
443
444} // namespace lely
445
446#endif // !LELY_UTIL_C_TYPE_HPP_
unique_c_ptr< T > make_unique_c(Args &&... args)
Creates an instance of a trivial, standard layout or incomplete C type and wraps it in a lely::unique...
Definition c_type.hpp:111
::std::unique_ptr< T, delete_c_type< T > > unique_c_ptr
A specialization of std::unique_ptr for trivial, standard layout or incomplete C types,...
Definition c_type.hpp:103
inline ::std::shared_ptr< T > make_shared_c(Args &&... args)
Creates an instance of a trivial, standard layout or incomplete C type and wraps it in a std::shared_...
Definition c_type.hpp:93
A CANopen value.
Definition val.hpp:42
The type of objects thrown as exceptions to report a failure to copy an instantiation of a C type.
Definition c_type.hpp:44
The type of objects thrown as exceptions to report a failure to initialize an instantiation of a C ty...
Definition c_type.hpp:38
The type of objects thrown as exceptions to report a failure to move an instantiation of a C type.
Definition c_type.hpp:50
The type of objects thrown as exceptions to report a system error with an associated error code.
Definition exception.hpp:54
The base class for a C++ interface to an incomplete C type.
Definition c_type.hpp:249
The base class for a C++ interface to a standard layout C type.
Definition c_type.hpp:174
@ ERRNUM_NOMEM
Not enough space.
Definition errnum.h:172
errnum_t get_errnum(void)
Returns the last (thread-specific) platform-independent error number set by a system call or library ...
Definition errnum.h:418
This header file is part of the utilities library; it contains the C++ exception declarations.
#define throw_or_abort(e)
If exceptions are disabled, aborts the process instead of throwing an exception.
Definition exception.hpp:38
A class template supplying a uniform interface to certain attributes of C types.
Definition c_type.hpp:350
The deleter for trivial, standard layout and incomplete C types.
Definition c_type.hpp:76
The base class for a C++ interface to a trivial C type.
Definition c_type.hpp:124