Zserio C++ runtime library  1.1.0
Built for Zserio 2.15.0
UniquePtr.h
Go to the documentation of this file.
1 #ifndef ZSERIO_UNIQUE_PTR_H_INC
2 #define ZSERIO_UNIQUE_PTR_H_INC
3 
4 #include <memory>
5 #include <type_traits>
6 
8 #include "zserio/RebindAlloc.h"
9 
10 namespace zserio
11 {
12 
13 namespace detail
14 {
15 
19 template <class ALLOC_T>
20 struct UniquePtrDeleter : public AllocatorHolder<ALLOC_T>
21 {
22  using allocator_type = ALLOC_T;
23  using T = typename allocator_type::value_type;
24 
27  ~UniquePtrDeleter() = default;
28 
29  UniquePtrDeleter(UniquePtrDeleter&& other) = default;
30  UniquePtrDeleter& operator=(UniquePtrDeleter&& other) = default;
39  UniquePtrDeleter(const UniquePtrDeleter& other) = delete;
40  UniquePtrDeleter& operator=(const UniquePtrDeleter& other) = delete;
48  template <typename ALLOC_U = ALLOC_T>
49  UniquePtrDeleter() :
50  UniquePtrDeleter(ALLOC_U())
51  {}
52 
56  template <typename ALLOC_U = ALLOC_T>
57  UniquePtrDeleter(const ALLOC_U& allocator) :
58  AllocatorHolder<ALLOC_T>(allocator)
59  {
60  static_assert(std::is_same<allocator_type, RebindAlloc<ALLOC_U, T>>::value,
61  "UniquePtrDeleter requires same allocator in constructor!");
62  }
63 
67  template <typename ALLOC_U>
68  UniquePtrDeleter(const UniquePtrDeleter<ALLOC_U>& deleter) :
69  UniquePtrDeleter(deleter.get_allocator())
70  {}
71 
72  void operator()(T* ptr)
73  {
74  allocator_type alloc = this->get_allocator();
75  using AllocTraits = std::allocator_traits<allocator_type>;
76  AllocTraits::destroy(alloc, std::addressof(*ptr));
77  AllocTraits::deallocate(alloc, ptr, 1);
78  }
79 };
80 
81 } // namespace detail
82 
88 template <typename T, typename ALLOC = std::allocator<T>>
89 using unique_ptr = std::unique_ptr<T, detail::UniquePtrDeleter<ALLOC>>;
90 
100 template <typename T, typename ALLOC, class... Args>
101 zserio::unique_ptr<T, RebindAlloc<ALLOC, T>> allocate_unique(const ALLOC& allocator, Args&&... args)
102 {
103  using Allocator = RebindAlloc<ALLOC, T>;
104  using AllocTraits = std::allocator_traits<Allocator>;
105 
106  Allocator typedAllocator = allocator;
107  typename AllocTraits::pointer ptr = AllocTraits::allocate(typedAllocator, 1);
108  try
109  {
110  AllocTraits::construct(typedAllocator, std::addressof(*ptr), std::forward<Args>(args)...);
111  return zserio::unique_ptr<T, Allocator>(std::addressof(*ptr), typedAllocator);
112  }
113  catch (...)
114  {
115  AllocTraits::deallocate(typedAllocator, ptr, 1);
116  throw;
117  }
118 }
119 
120 } // namespace zserio
121 
122 #endif // ZSERIO_UNIQUE_PTR_H_INC
AllocatorHolder & operator=(const AllocatorHolder &other)=default
allocator_type get_allocator() const
zserio::unique_ptr< T, RebindAlloc< ALLOC, T > > allocate_unique(const ALLOC &allocator, Args &&... args)
Definition: UniquePtr.h:101
typename std::allocator_traits< ALLOC >::template rebind_alloc< T > RebindAlloc
Definition: RebindAlloc.h:10
std::unique_ptr< T, detail::UniquePtrDeleter< ALLOC > > unique_ptr
Definition: UniquePtr.h:89