Lely core libraries 1.9.2
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>
93make_shared_c(Args&&... args) {
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>
111make_unique_c(Args&&... args) {
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 c_const_reference
140 c_ref() const noexcept {
141 return *c_ptr();
142 }
143
144 c_pointer
145 c_ptr() noexcept {
146 return reinterpret_cast<c_pointer>(this);
147 }
148
149 c_const_pointer
150 c_ptr() const noexcept {
151 return reinterpret_cast<c_const_pointer>(this);
152 }
153
154 static void
155 dtor(trivial_c_type* p) noexcept {
156 delete p;
157 }
158 void
159 destroy() noexcept {
160 dtor(this);
161 }
162};
163
164template <class T>
165inline void
166destroy(trivial_c_type<T>* p) noexcept {
167 p->destroy();
168}
169
171template <class T>
173 public:
174 typedef typename c_type_traits<T>::value_type c_value_type;
175 typedef typename c_type_traits<T>::reference c_reference;
176 typedef typename c_type_traits<T>::const_reference c_const_reference;
177 typedef typename c_type_traits<T>::pointer c_pointer;
178 typedef typename c_type_traits<T>::const_pointer c_const_pointer;
179
180 operator c_value_type() const noexcept { return c_ref(); }
181 operator c_reference() noexcept { return c_ref(); }
182 operator c_const_reference() const noexcept { return c_ref(); }
183
184 c_reference
185 c_ref() noexcept {
186 return *c_ptr();
187 }
188 c_const_reference
189 c_ref() const noexcept {
190 return *c_ptr();
191 }
192
193 c_pointer
194 c_ptr() noexcept {
195 return reinterpret_cast<c_pointer>(this);
196 }
197
198 c_const_pointer
199 c_ptr() const noexcept {
200 return reinterpret_cast<c_const_pointer>(this);
201 }
202
203 static void
204 dtor(standard_c_type* p) noexcept {
205 delete p;
206 }
207 void
208 destroy() noexcept {
209 dtor(this);
210 }
211
213 operator=(const standard_c_type& val) {
214 if (!c_type_traits<T>::copy(c_ptr(), val.c_ptr())) impl::throw_bad_copy();
215 return *this;
216 }
217
219 operator=(standard_c_type&& val) {
220 if (!c_type_traits<T>::move(c_ptr(), val.c_ptr())) impl::throw_bad_move();
221 return *this;
222 }
223
224 protected:
225 template <class... Args>
226 explicit standard_c_type(Args&&... args) {
227 if (!c_type_traits<T>::init(c_ptr(), std::forward<Args>(args)...))
228 impl::throw_bad_init();
229 }
230
232};
233
234template <class T>
235inline void
236destroy(standard_c_type<T>* p) noexcept {
237 p->destroy();
238}
239
244template <class T>
246 public:
247 typedef typename c_type_traits<T>::value_type c_value_type;
248 typedef typename c_type_traits<T>::reference c_reference;
249 typedef typename c_type_traits<T>::const_reference c_const_reference;
250 typedef typename c_type_traits<T>::pointer c_pointer;
251 typedef typename c_type_traits<T>::const_pointer c_const_pointer;
252
253 operator c_reference() noexcept { return c_ref(); }
254 operator c_const_reference() const noexcept { return c_ref(); }
255
256 c_reference
257 c_ref() noexcept {
258 return *c_ptr();
259 }
260 c_const_reference
261 c_ref() const noexcept {
262 return *c_ptr();
263 }
264
265 c_pointer
266 c_ptr() noexcept {
267 return reinterpret_cast<c_pointer>(this);
268 }
269
270 c_const_pointer
271 c_ptr() const noexcept {
272 return reinterpret_cast<c_const_pointer>(this);
273 }
274
275 static void
276 dtor(incomplete_c_type* p) noexcept {
277 delete p;
278 }
279 void
280 destroy() noexcept {
281 dtor(this);
282 }
283
284 static void*
285 operator new(std::size_t size) {
286 void* ptr = operator new(size, ::std::nothrow);
287 if (!ptr) throw_or_abort(std::bad_alloc());
288 return ptr;
289 }
290
291 static void*
292 operator new(std::size_t, const ::std::nothrow_t&) noexcept {
294 }
295
296 static void
297 operator delete(void* ptr) noexcept {
298 operator delete(ptr, ::std::nothrow);
299 }
300
301 static void
302 operator delete(void* ptr, const ::std::nothrow_t&)noexcept {
304 }
305
307 operator=(const incomplete_c_type& val) {
308 if (!c_type_traits<T>::copy(c_ptr(), val.c_ptr())) impl::throw_bad_copy();
309 return *this;
310 }
311
313 operator=(incomplete_c_type&& val) {
314 if (!c_type_traits<T>::move(c_ptr(), val.c_ptr())) impl::throw_bad_move();
315 return *this;
316 }
317
318 static void* operator new[](std::size_t) = delete;
319 static void* operator new[](std::size_t, const ::std::nothrow_t&) = delete;
320 static void operator delete[](void*) = delete;
321 static void operator delete[](void*, const ::std::nothrow_t&) = delete;
322
323 protected:
324 template <class... Args>
325 explicit incomplete_c_type(Args&&... args) {
326 if (!c_type_traits<T>::init(c_ptr(), ::std::forward<Args>(args)...))
327 impl::throw_bad_init();
328 }
329
331};
332
333template <class T>
334inline void
335destroy(incomplete_c_type<T>* p) noexcept {
336 p->destroy();
337}
338
343template <class T>
345 typedef T value_type;
346 typedef value_type& reference;
347 typedef const value_type& const_reference;
348 typedef value_type* pointer;
349 typedef const value_type* const_pointer;
350
351 static void*
352 alloc() noexcept {
353 return operator new(sizeof(T), ::std::nothrow);
354 }
355
356 static void
357 free(void* ptr) noexcept {
358 operator delete(ptr, ::std::nothrow);
359 }
360
361 static pointer
362 init(pointer p) noexcept {
363 return p;
364 }
365
366 static pointer
367 init(pointer p, const T& val) noexcept {
368 return new (static_cast<void*>(p)) T(val);
369 }
370
371 static void
372 fini(pointer p) noexcept {
373 p->~T();
374 }
375
376 static pointer
377 copy(pointer p1, const_pointer p2) noexcept {
378 *p1 = *p2;
379 return p1;
380 }
381
382 static pointer
383 move(pointer p1, pointer p2) noexcept {
384 *p1 = ::std::move(*p2);
385 return p1;
386 }
387};
388
393template <>
394struct c_type_traits<void> {
395 typedef void value_type;
396 typedef struct {
397 } __type;
398 typedef __type& reference;
399 typedef const __type& const_reference;
400 typedef value_type* pointer;
401 typedef const value_type* const_pointer;
402
403 static void*
404 alloc() noexcept {
405 return operator new(0, ::std::nothrow);
406 }
407
408 static void
409 free(void* ptr) noexcept {
410 operator delete(ptr, ::std::nothrow);
411 }
412
413 static pointer
414 init(pointer p) noexcept {
415 return p;
416 }
417
418 static void
419 fini(pointer p) noexcept {
420 (void)p;
421 }
422
423 static pointer
424 copy(pointer p1, const_pointer p2) noexcept {
425 (void)p2;
426
427 return p1;
428 }
429
430 static pointer
431 move(pointer p1, pointer p2) noexcept {
432 (void)p2;
433
434 return p1;
435 }
436};
437
438} // namespace lely
439
440#endif // !LELY_UTIL_C_TYPE_HPP_
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:245
The base class for a C++ interface to a standard layout C type.
Definition: c_type.hpp:172
@ ERRNUM_NOMEM
Not enough space.
Definition: errnum.h:169
errnum_t get_errnum(void)
Returns the last (thread-specific) platform-independent error number set by a system call or library ...
Definition: errnum.h:369
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
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
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 class template supplying a uniform interface to certain attributes of C types.
Definition: c_type.hpp:344
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