Zserio C++ runtime library  1.4.2
Built for Zserio 2.19.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 
72  template <typename ALLOC_U>
73  UniquePtrDeleter(const UniquePtrDeleter<ALLOC_U>& deleter) = delete;
74 
75  void operator()(T* ptr)
76  {
77  allocator_type alloc = this->get_allocator();
78  using AllocTraits = std::allocator_traits<allocator_type>;
79  AllocTraits::destroy(alloc, std::addressof(*ptr));
80  AllocTraits::deallocate(alloc, ptr, 1);
81  }
82 };
83 
84 } // namespace detail
85 
91 template <typename T, typename ALLOC = std::allocator<T>>
92 using unique_ptr = std::unique_ptr<T, detail::UniquePtrDeleter<ALLOC>>;
93 
103 template <typename T, typename ALLOC, class... Args>
104 zserio::unique_ptr<T, RebindAlloc<ALLOC, T>> allocate_unique(const ALLOC& allocator, Args&&... args)
105 {
106  using Allocator = RebindAlloc<ALLOC, T>;
107  using AllocTraits = std::allocator_traits<Allocator>;
108 
109  Allocator typedAllocator = allocator;
110  typename AllocTraits::pointer ptr = AllocTraits::allocate(typedAllocator, 1);
111  try
112  {
113  AllocTraits::construct(typedAllocator, std::addressof(*ptr), std::forward<Args>(args)...);
114  return zserio::unique_ptr<T, Allocator>(std::addressof(*ptr), typedAllocator);
115  }
116  catch (...)
117  {
118  AllocTraits::deallocate(typedAllocator, ptr, 1);
119  throw;
120  }
121 }
122 
123 } // namespace zserio
124 
125 #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:104
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:92