openPMD-api
UniquePtr.hpp
1 #pragma once
2 
3 #include <functional>
4 #include <iostream>
5 #include <memory>
6 #include <type_traits>
7 
8 namespace openPMD
9 {
10 
11 namespace auxiliary
12 {
24  template <typename T>
25  class CustomDelete : public std::function<void(std::remove_extent_t<T> *)>
26  {
27  private:
28  using T_decayed = std::remove_extent_t<T>;
29 
30  public:
31  using deleter_type = std::function<void(T_decayed *)>;
32 
33  deleter_type const &get_deleter() const
34  {
35  return *this;
36  }
37  deleter_type &get_deleter()
38  {
39  return *this;
40  }
41 
42  /*
43  * Default constructor: Use std::default_delete<T>.
44  * This ensures correct destruction of arrays by using delete[].
45  */
46  CustomDelete()
47  : deleter_type{[](T_decayed *ptr) {
48  if constexpr (std::is_void_v<T_decayed>)
49  {
50  (void)ptr;
51  std::cerr << "[Warning] Cannot standard-delete a void-type "
52  "pointer. Please specify a custom destructor. "
53  "Will let the memory leak."
54  << std::endl;
55  }
56  else
57  {
58  std::default_delete<T>{}(ptr);
59  }
60  }}
61  {}
62 
63  CustomDelete(deleter_type func) : deleter_type(std::move(func))
64  {}
65  };
66 } // namespace auxiliary
67 
85 template <typename T>
87  : public std::unique_ptr<
88  T,
89  /* Deleter = */ auxiliary::CustomDelete<T>>
90 {
91 private:
92  using BasePtr = std::unique_ptr<T, auxiliary::CustomDelete<T>>;
93 
94 public:
95  using T_decayed = std::remove_extent_t<T>;
96 
97  UniquePtrWithLambda() = default;
98 
100  UniquePtrWithLambda &operator=(UniquePtrWithLambda &&) = default;
101 
102  UniquePtrWithLambda(UniquePtrWithLambda const &) = delete;
103  UniquePtrWithLambda &operator=(UniquePtrWithLambda const &) = delete;
104 
108  UniquePtrWithLambda(std::unique_ptr<T>);
109 
115  template <typename Del>
116  UniquePtrWithLambda(std::unique_ptr<T, Del>);
117 
121  UniquePtrWithLambda(T_decayed *);
122 
126  UniquePtrWithLambda(T_decayed *, std::function<void(T_decayed *)>);
127 
135  template <typename U>
136  UniquePtrWithLambda<U> static_cast_() &&;
137 };
138 
139 template <typename T>
141  : BasePtr{stdPtr.release()}
142 {}
143 
144 template <typename T>
145 template <typename Del>
147  : BasePtr{
148  ptr.release(),
150  [deleter = std::move(ptr.get_deleter())](T_decayed *del_ptr) {
151  deleter.get_deleter()(del_ptr);
152  }}}
153 {}
154 
155 template <typename T>
156 UniquePtrWithLambda<T>::UniquePtrWithLambda(T_decayed *ptr) : BasePtr{ptr}
157 {}
158 
159 template <typename T>
161  T_decayed *ptr, std::function<void(T_decayed *)> deleter)
162  : BasePtr{ptr, std::move(deleter)}
163 {}
164 
165 template <typename T>
166 template <typename U>
168 {
169  using other_type = std::remove_extent_t<U>;
170  return UniquePtrWithLambda<U>{
171  static_cast<other_type *>(this->release()),
172  [deleter = std::move(this->get_deleter())](other_type *ptr) {
173  deleter.get_deleter()(static_cast<T_decayed *>(ptr));
174  }};
175 }
176 } // namespace openPMD
Unique Pointer class that uses a dynamic destructor type.
Definition: UniquePtr.hpp:86
Public definitions of openPMD-api.
Custom deleter type based on std::function.
Definition: UniquePtr.hpp:25