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  /*
34  * Default constructor: Use std::default_delete<T>.
35  * This ensures correct destruction of arrays by using delete[].
36  */
37  CustomDelete()
38  : deleter_type{[]([[maybe_unused]] T_decayed *ptr) {
39  if constexpr (std::is_void_v<T_decayed>)
40  {
41  std::cerr << "[Warning] Cannot standard-delete a void-type "
42  "pointer. Please specify a custom destructor. "
43  "Will let the memory leak."
44  << std::endl;
45  }
46  else
47  {
48  std::default_delete<T>{}(ptr);
49  }
50  }}
51  {}
52 
53  CustomDelete(deleter_type func) : deleter_type(std::move(func))
54  {}
55  };
56 } // namespace auxiliary
57 
75 template <typename T>
77  : public std::unique_ptr<
78  T,
79  /* Deleter = */ auxiliary::CustomDelete<T>>
80 {
81 private:
82  using BasePtr = std::unique_ptr<T, auxiliary::CustomDelete<T>>;
83 
84 public:
85  using T_decayed = std::remove_extent_t<T>;
86 
87  UniquePtrWithLambda() = default;
88 
90  UniquePtrWithLambda &operator=(UniquePtrWithLambda &&) = default;
91 
92  UniquePtrWithLambda(UniquePtrWithLambda const &) = delete;
93  UniquePtrWithLambda &operator=(UniquePtrWithLambda const &) = delete;
94 
98  UniquePtrWithLambda(std::unique_ptr<T>);
99 
105  template <typename Del>
106  UniquePtrWithLambda(std::unique_ptr<T, Del>);
107 
111  UniquePtrWithLambda(T_decayed *);
112 
116  UniquePtrWithLambda(T_decayed *, std::function<void(T_decayed *)>);
117 
125  template <typename U>
127 };
128 
129 template <typename T>
131  : BasePtr{stdPtr.release()}
132 {}
133 
134 template <typename T>
135 template <typename Del>
137  : BasePtr{ptr.release(), auxiliary::CustomDelete<T>{[&]() {
138  if constexpr (std::is_copy_constructible_v<Del>)
139  {
140  return [deleter = std::move(ptr.get_deleter())](
141  T_decayed *del_ptr) { deleter(del_ptr); };
142  }
143  else
144  {
145  /*
146  * The constructor of std::function requires a copyable
147  * lambda. Since Del is not a copyable type, we cannot
148  * capture it directly, but need to put it into a
149  * shared_ptr to make it copyable.
150  */
151  return [deleter = std::make_shared<Del>(
152  std::move(ptr.get_deleter()))](
153  T_decayed *del_ptr) { (*deleter)(del_ptr); };
154  }
155  }()}}
156 {}
157 
158 template <typename T>
159 UniquePtrWithLambda<T>::UniquePtrWithLambda(T_decayed *ptr) : BasePtr{ptr}
160 {}
161 
162 template <typename T>
164  T_decayed *ptr, std::function<void(T_decayed *)> deleter)
165  : BasePtr{ptr, std::move(deleter)}
166 {}
167 
168 template <typename T>
169 template <typename U>
171 {
172  using other_type = std::remove_extent_t<U>;
173  return UniquePtrWithLambda<U>{
174  static_cast<other_type *>(this->release()),
175  [deleter = std::move(this->get_deleter())](other_type *ptr) {
176  deleter(static_cast<T_decayed *>(ptr));
177  }};
178 }
179 } // namespace openPMD
Unique Pointer class that uses a dynamic destructor type.
Definition: UniquePtr.hpp:80
UniquePtrWithLambda(T_decayed *)
Construct from raw pointer with default deleter.
Definition: UniquePtr.hpp:159
UniquePtrWithLambda(T_decayed *, std::function< void(T_decayed *)>)
Construct from raw pointer with custom deleter.
Definition: UniquePtr.hpp:163
UniquePtrWithLambda(std::unique_ptr< T, Del >)
Conversion constructor from std::unique_ptr<T> with custom deleter.
Definition: UniquePtr.hpp:136
UniquePtrWithLambda(std::unique_ptr< T >)
Conversion constructor from std::unique_ptr<T> with default deleter.
Definition: UniquePtr.hpp:130
UniquePtrWithLambda< U > static_cast_() &&
Like std::static_pointer_cast.
Custom deleter type based on std::function.
Definition: UniquePtr.hpp:26
Public definitions of openPMD-api.
Definition: Date.cpp:29