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 
25 #include <lely/util/exception.hpp>
26 
27 #include <algorithm>
28 #include <memory>
29 #include <new>
30 #include <utility>
31 
32 namespace lely {
33 
38 class bad_init : public error {};
39 
44 class bad_copy : public error {};
45 
50 class bad_move : public error {};
51 
52 namespace impl {
53 
54 inline void
55 throw_bad_init() {
56  if (get_errnum() == ERRNUM_NOMEM) throw_or_abort(::std::bad_alloc());
58 }
59 
60 inline void
61 throw_bad_copy() {
62  if (get_errnum() == ERRNUM_NOMEM) throw_or_abort(::std::bad_alloc());
63  throw_or_abort(bad_copy());
64 }
65 
66 inline void
67 throw_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 
75 template <class T>
76 struct delete_c_type {
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 
91 template <class T, class... Args>
92 inline ::std::shared_ptr<T>
93 make_shared_c(Args&&... args) {
94  return ::std::shared_ptr<T>(new T(::std::forward<Args>(args)...),
96 }
97 
102 template <class T>
103 using unique_c_ptr = ::std::unique_ptr<T, delete_c_type<T>>;
104 
109 template <class T, class... Args>
110 inline unique_c_ptr<T>
111 make_unique_c(Args&&... args) {
112  return unique_c_ptr<T>(new T(::std::forward<Args>(args)...));
113 }
114 
119 template <class T>
121 
123 template <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 
164 template <class T>
165 inline void
166 destroy(trivial_c_type<T>* p) noexcept {
167  p->destroy();
168 }
169 
171 template <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 
231  ~standard_c_type() { c_type_traits<T>::fini(c_ptr()); }
232 };
233 
234 template <class T>
235 inline void
236 destroy(standard_c_type<T>* p) noexcept {
237  p->destroy();
238 }
239 
244 template <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 {
293  return c_type_traits<T>::alloc();
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 
333 template <class T>
334 inline void
335 destroy(incomplete_c_type<T>* p) noexcept {
336  p->destroy();
337 }
338 
343 template <class T>
344 struct c_type_traits {
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 
393 template <>
394 struct 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_
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
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 trivial C type.
Definition: c_type.hpp:124
The type of objects thrown as exceptions to report a failure to copy an instantiation of a C type...
Definition: c_type.hpp:44
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
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 a standard layout C type.
Definition: c_type.hpp:172
The type of objects thrown as exceptions to report a failure to initialize an instantiation of a C ty...
Definition: c_type.hpp:38
This header file is part of the utilities library; it contains the C++ exception declarations.
::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, using lely::delete_c_type as the deleter.
Definition: c_type.hpp:103
The type of objects thrown as exceptions to report a failure to move an instantiation of a C type...
Definition: c_type.hpp:50
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
Not enough space.
Definition: errnum.h:169
Global namespace for the Lely Industries N.V. libraries.
Definition: buf.hpp:32
The deleter for trivial, standard layout and incomplete C types.
Definition: c_type.hpp:76
A class template supplying a uniform interface to certain attributes of C types.
Definition: c_type.hpp:120
#define throw_or_abort(e)
If exceptions are disabled, aborts the process instead of throwing an exception.
Definition: exception.hpp:38