nlib
UniquePtr.h
Go to the documentation of this file.
1 
2 #pragma once
3 #ifndef INCLUDE_NN_NLIB_UNIQUEPTR_H_
4 #define INCLUDE_NN_NLIB_UNIQUEPTR_H_
5 
6 #include <stdlib.h>
7 #include <memory>
8 
9 #include "nn/nlib/Config.h"
10 #include "nn/nlib/Swap.h"
11 #include "nn/nlib/Hash.h"
12 #include "nn/nlib/TypeTraits.h"
13 
14 #if defined(NLIB_CXX11_UNIQUEPTR) && defined(NLIB_CXX11_TEMPLATE_ALIAS)
15 NLIB_NAMESPACE_BEGIN
16 
17 template <class T, class DEL = std::default_delete<T> >
18 using UniquePtr = std::unique_ptr<T, DEL>;
19 template <class T>
20 using DefaultDelete = std::default_delete<T>;
21 
22 NLIB_NAMESPACE_END
23 #else
24 #include <algorithm> // NOLINT
25 
26 NLIB_NAMESPACE_BEGIN
27 
28 template <class T>
29 struct DefaultDelete {
30  void operator()(T* p) const NLIB_NOEXCEPT {
31  NLIB_STATIC_ASSERT(sizeof(T));
32  if (p) delete p;
33  }
34 };
35 
36 template <class T>
37 struct DefaultDelete<T[]> {
38  void operator()(T* p) const NLIB_NOEXCEPT {
39  NLIB_STATIC_ASSERT(sizeof(T));
40  if (p) delete[] p;
41  }
42 };
43 
44 NLIB_STATIC_ASSERT(IsEmpty<DefaultDelete<int> >::value&& IsEmpty<DefaultDelete<int[]> >::value); // NOLINT
45 
46 namespace detail {
47 
48 template <class T, class DEL, bool DEL_EMPTY>
49 class UniquePtrBase {
50  public:
51  UniquePtrBase() : m_Ptr(NULL), m_Deleter() {}
52  explicit UniquePtrBase(T* ptr) : m_Ptr(ptr), m_Deleter() {}
53  UniquePtrBase(T* ptr, const DEL& del) : m_Ptr(ptr), m_Deleter(del) {}
54 
55  protected:
56  DEL& get_deleter() { return m_Deleter; }
57  const DEL& get_deleter() const { return m_Deleter; }
58  T* m_Ptr;
59  DEL m_Deleter;
60  void Swap(UniquePtrBase& rhs) NLIB_NOEXCEPT { // NOLINT
61  using std::swap;
62  swap(this->m_Ptr, rhs.m_Ptr);
63  swap(this->m_Deleter, rhs.m_Deleter);
64  }
65  NLIB_DISALLOW_COPY_AND_ASSIGN(UniquePtrBase);
66 };
67 
68 template <class T, class DEL>
69 class UniquePtrBase<T, DEL, true> : public DEL {
70  public:
71  UniquePtrBase() : m_Ptr(NULL) {}
72  explicit UniquePtrBase(T* ptr) : m_Ptr(ptr) {}
73  UniquePtrBase(T* ptr, const DEL& del) : DEL(del), m_Ptr(ptr) {}
74 
75  protected:
76  DEL& get_deleter() { return *this; }
77  const DEL& get_deleter() const { return *this; }
78  T* m_Ptr;
79  void Swap(UniquePtrBase& rhs) NLIB_NOEXCEPT { // NOLINT
80  using std::swap;
81  swap(this->m_Ptr, rhs.m_Ptr);
82  }
83  NLIB_DISALLOW_COPY_AND_ASSIGN(UniquePtrBase);
84 };
85 
86 template<class S>
87 struct IsCompleteType
88  : public IntegralConstant<bool, (sizeof(S) != 0 || sizeof(S) == 0)> {};
89 
90 template<>
91 struct IsCompleteType<void> : public TrueType {};
92 
93 } // namespace detail
94 
95 template <class T, class DEL = DefaultDelete<T> >
96 class UniquePtr NLIB_FINAL : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
97  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
98 
99  public:
100  typedef T* pointer_type; // simpler definition than std::unique_ptr
101  typedef DEL deleter_type; // note that DEL cannot have data members
102  typedef T element_type;
103 
105  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
106  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
107  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
108  NLIB_MOVE_MEMBER_HELPER_1(UniquePtr, BaseType)
110  NLIB_STATIC_ASSERT(detail::IsCompleteType<T>::value);
111  // typedef char is_complete_type[sizeof(T) ? 1 : -1];
112  // (void) sizeof(is_complete_type);
113  if (this->m_Ptr) get_deleter()(this->m_Ptr);
114  }
115  void reset(T* p = 0) NLIB_NOEXCEPT {
116  // NOTE:
117  // this->m_Ptr is for CTR
118  if (p != this->m_Ptr) {
119  T* old = this->m_Ptr;
120  this->m_Ptr = p;
121  if (old) get_deleter()(old);
122  }
123  }
124  typename AddRef<T>::type operator*() const {
125  NLIB_ASSERT(this->m_Ptr != NULL);
126  return *this->m_Ptr;
127  }
129  NLIB_ASSERT(this->m_Ptr != NULL);
130  return this->m_Ptr;
131  }
132  T* get() const NLIB_NOEXCEPT { return this->m_Ptr; }
134  T* p = this->m_Ptr;
135  this->m_Ptr = NULL;
136  return p;
137  }
138  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { // NOLINT
139  this->Swap(rhs);
140  }
142  this->reset();
143  return *this;
144  }
145  size_t GetHash() const { return Hash<T*>()(this->get()); }
146  DEL& get_deleter() { return BaseType::get_deleter(); }
147  const DEL& get_deleter() const { return BaseType::get_deleter(); }
148 
149  NLIB_SAFE_BOOL(UniquePtr, this->m_Ptr != NULL);
150 
151  private:
152  template <class S, class D>
153  bool operator==(const UniquePtr<S, D>& p) const;
154  template <class S, class D>
155  bool operator!=(const UniquePtr<S, D>& p) const;
157 };
158 
159 template <class T, class DEL>
160 class UniquePtr<T[], DEL> : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
161  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
162 
163  public:
164  typedef T* pointer_type; // simpler definition than std::unique_ptr
165  typedef DEL deleter_type;
166  typedef T element_type;
167 
168  NLIB_CEXPR UniquePtr() NLIB_NOEXCEPT : BaseType() {}
169  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
170  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
171  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
172  NLIB_MOVE_MEMBER_HELPER_1(UniquePtr, BaseType)
173  ~UniquePtr() NLIB_NOEXCEPT {
174  NLIB_STATIC_ASSERT(sizeof(T));
175  get_deleter()(this->m_Ptr);
176  }
177  void reset(T* p = 0) NLIB_NOEXCEPT {
178  // NOTE:
179  // this->m_Ptr is for CTR
180  if (p != this->m_Ptr) {
181  T* old = this->m_Ptr;
182  this->m_Ptr = p;
183  if (old) get_deleter()(old);
184  }
185  }
186  T& operator*() const {
187  NLIB_ASSERT(this->m_Ptr != NULL);
188  return *this->m_Ptr;
189  }
190  T* operator->() const NLIB_NOEXCEPT {
191  NLIB_ASSERT(this->m_Ptr != NULL);
192  return this->m_Ptr;
193  }
194  T* get() const NLIB_NOEXCEPT { return this->m_Ptr; }
195  T* release() NLIB_NOEXCEPT {
196  T* p = this->m_Ptr;
197  this->m_Ptr = NULL;
198  return p;
199  }
200  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { // NOLINT
201  this->Swap(rhs);
202  }
203  T& operator[](size_t n) { return get()[n]; }
204  const T& operator[](size_t n) const { return get()[n]; }
205  size_t GetHash() const { return Hash<T*>()(this->get()); }
206  DEL& get_deleter() { return BaseType::get_deleter(); }
207  const DEL& get_deleter() const { return BaseType::get_deleter(); }
208 
209  NLIB_SAFE_BOOL(UniquePtr, this->m_Ptr != NULL);
210 
211  private:
212  template <class S, class D>
213  bool operator==(const UniquePtr<S, D>& p) const;
214  template <class S, class D>
215  bool operator!=(const UniquePtr<S, D>& p) const;
217 };
218 
219 template <class T1, class D1, class T2, class D2>
221  return rhs.get() == lhs.get();
222 }
223 
224 template <class T1, class D1>
225 bool operator==(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
226  return !lhs;
227 }
228 
229 template <class T1, class D1>
230 bool operator==(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
231  return !rhs;
232 }
233 
234 template <class T1, class D1, class T2, class D2>
236  return rhs.get() != lhs.get();
237 }
238 
239 template <class T1, class D1>
240 bool operator!=(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
241  return static_cast<bool>(lhs);
242 }
243 
244 template <class T1, class D1>
245 bool operator!=(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
246  return static_cast<bool>(rhs);
247 }
248 
249 NLIB_NAMESPACE_END
250 
251 #ifndef NLIB_STD_SWAP_WORKAROUND
252 NLIB_NAMESPACE_BEGIN
253 #else
254 NLIB_DEFINE_STD_SWAP_T_BEGIN1(std) // NOLINT
255 #endif
256 
257 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::UniquePtr) // NOLINT
258 
259 #ifndef NLIB_STD_SWAP_WORKAROUND
260 NLIB_NAMESPACE_END
261 #else
262 NLIB_DEFINE_STD_SWAP_T_END1(std) // NOLINT
263 #endif
264 
265 #ifndef NLIB_CXX11_TEMPLATE_ALIAS
266 NLIB_NAMESPACE_BEGIN
267 #else
268 NLIB_DEFINE_STD_HASH_T_BEGIN1(std) // NOLINT
269 #endif
270 
271 NLIB_DEFINE_STD_HASH_T2(T, DEL, NLIB_NS::UniquePtr) // NOLINT
272 
273 #ifndef NLIB_CXX11_TEMPLATE_ALIAS
274 NLIB_NAMESPACE_END
275 #else
276 NLIB_DEFINE_STD_HASH_T_END1(std) // NOLINT
277 #endif
278 
279 #endif
280 
281 NLIB_NAMESPACE_BEGIN
282 
283 /*
284 template<class T, void FreeFunc(void*) = free>
285 struct FreeDeleterT {
286  void operator()(T* p) const NLIB_NOEXCEPT {
287  NLIB_STATIC_ASSERT(sizeof(T));
288  NLIB_STATIC_ASSERT(IsPod<T>::value);
289  if (p) FreeFunc(p);
290  }
291 };
292 */
293 
294 namespace detail {
295 
296 template <class T, class ALLOC, bool DEL_EMPTY>
297 class DefaultDeleteExBase {
298  public:
299  DefaultDeleteExBase() : al() {}
300  explicit DefaultDeleteExBase(const ALLOC& al_) : al(al_) {}
301 
302  protected:
303  ALLOC& get_allocator() { return al; }
304  ALLOC al;
305 
306  private:
307  NLIB_DISALLOW_COPY_AND_ASSIGN(DefaultDeleteExBase);
308 };
309 
310 template <class T, class ALLOC>
311 class DefaultDeleteExBase<T, ALLOC, true> : public ALLOC {
312  public:
313  DefaultDeleteExBase() {}
314  explicit DefaultDeleteExBase(const ALLOC& al_) { NLIB_UNUSED(al_); }
315 
316  protected:
317  ALLOC& get_allocator() { return *this; }
318 };
319 
320 } // namespace detail
321 
322 template <class T, class ALLOC = std::allocator<T> >
323 struct DefaultDeleteEx : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
324  void operator()(T* p)NLIB_NOEXCEPT {
325  NLIB_STATIC_ASSERT(sizeof(T));
326  NLIB_STATIC_ASSERT(!IsArray<T>::value);
327  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
328  if (p) {
329  ALLOC& al = BaseType::get_allocator();
330  al.destroy(p);
331  al.deallocate(p, 1);
332  }
333  }
334 };
335 
336 template <class T, class ALLOC>
337 struct DefaultDeleteEx<T[], ALLOC>
338  : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
339  // mainly for using malloc variant like nmalloc
340  // ex.
341  // UniquePtr<
342  // unsigned char[],
343  // DefaultDeleteEx<unsigned char[], NMallocStlAllocator<unsigned char> >
344  // >
345  void operator()(T* p)NLIB_NOEXCEPT {
346  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
347  NLIB_STATIC_ASSERT(sizeof(T));
348  NLIB_STATIC_ASSERT(IsPod<T>::value);
349  if (p) {
350  ALLOC& al = BaseType::get_allocator();
351  // The length is unknown
352  al.deallocate(p, 1);
353  }
354  }
355 };
356 
357 NLIB_NAMESPACE_END
358 
359 #endif // INCLUDE_NN_NLIB_UNIQUEPTR_H_
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Platform.h:2151
~UniquePtr() noexcept
Destructor. If the pointer is not NULL, executes the deleter and deletes.
Definition: UniquePtr.h:109
UniquePtr(T *p) noexcept
Sets a pointer.
Definition: UniquePtr.h:106
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
DEL & get_deleter()
Gets the deleter.
Definition: UniquePtr.h:146
T * operator->() const noexcept
Returns the pointer.
Definition: UniquePtr.h:128
constexpr UniquePtr(nullptr_t) noexcept
This function is called if nullptr has been passed to a parameter.
Definition: UniquePtr.h:105
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
Prohibits use of the copy constructor and assignment operator for the class specified by TypeName...
Definition: Config.h:126
#define NLIB_SAFE_BOOL(class_name, exp)
Defines a safe operator bool function in the class. Uses the C++11 explicit bool if it is available f...
Definition: Config.h:141
STL namespace.
T element_type
Defines T using typedef.
Definition: UniquePtr.h:102
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Definition: UniquePtr.h:96
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are equal.
Definition: NMalloc.h:101
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:106
void reset(T *p=0) noexcept
Replaces a pointer. The replaced pointer is deleted.
Definition: UniquePtr.h:115
constexpr UniquePtr() noexcept
Instantiates the object with default parameters (default constructor).
Definition: UniquePtr.h:104
UniquePtr & operator=(nullptr_t) noexcept
Substitutes for nullptr.
Definition: UniquePtr.h:141
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
void swap(UniquePtr &rhs) noexcept
Swaps the pointer that is being stored.
Definition: UniquePtr.h:138
size_t GetHash() const
Computes the hash value for the pointer and returns the calculation result.
Definition: UniquePtr.h:145
const DEL & get_deleter() const
Gets the deleter.
Definition: UniquePtr.h:147
DEL deleter_type
Defines DEL using typedef.
Definition: UniquePtr.h:101
A file that contains the configuration information for each development environment.
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
Increases rhs by a factor of i.
Definition: DateTime.h:213
AddRef< T >::type operator*() const
Dereferences the pointer.
Definition: UniquePtr.h:124
UniquePtr(T *p, const DEL &del)
Sets a pointer and a deleter.
Definition: UniquePtr.h:107
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:117
T * pointer_type
Defines T* using typedef.
Definition: UniquePtr.h:100
T * release() noexcept
Release ownership of the pointer and returns the pointer.
Definition: UniquePtr.h:133