Lely core libraries  2.2.5
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());
64 }
65 
66 inline void
67 throw_bad_move() {
68  if (get_errnum() == ERRNUM_NOMEM) throw_or_abort(::std::bad_alloc());
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 
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 
166 template <class T>
167 inline void
168 destroy(trivial_c_type<T>* p) noexcept {
169  p->destroy();
170 }
171 
173 template <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 
235  ~standard_c_type() { c_type_traits<T>::fini(c_ptr()); }
236 };
237 
238 template <class T>
239 inline void
240 destroy(standard_c_type<T>* p) noexcept {
241  p->destroy();
242 }
243 
248 template <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 {
299  return c_type_traits<T>::alloc();
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 
339 template <class T>
340 inline void
341 destroy(incomplete_c_type<T>* p) noexcept {
342  p->destroy();
343 }
344 
349 template <class T>
350 struct c_type_traits {
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 
399 template <>
400 struct c_type_traits<void> {
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_
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
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:249
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
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:174
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.
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
Definition: buf.hpp:32
::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 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