nlib
UniquePtr.h
Go to the documentation of this file.
1 
2 /*--------------------------------------------------------------------------------*
3  Project: CrossRoad
4  Copyright (C)Nintendo All rights reserved.
5 
6  These coded instructions, statements, and computer programs contain proprietary
7  information of Nintendo and/or its licensed developers and are protected by
8  national and international copyright laws. They may not be disclosed to third
9  parties or copied or duplicated in any form, in whole or in part, without the
10  prior written consent of Nintendo.
11 
12  The content herein is highly confidential and should be handled accordingly.
13  *--------------------------------------------------------------------------------*/
14 
15 #pragma once
16 #ifndef INCLUDE_NN_NLIB_UNIQUEPTR_H_
17 #define INCLUDE_NN_NLIB_UNIQUEPTR_H_
18 
19 #include <stdlib.h>
20 #include <memory>
21 
22 #include "nn/nlib/Config.h"
23 #include "nn/nlib/Swap.h"
24 #include "nn/nlib/Hash.h"
25 #include "nn/nlib/TypeTraits.h"
26 
27 #if defined(NLIB_CXX11_UNIQUEPTR) && defined(__cpp_alias_templates)
28 NLIB_NAMESPACE_BEGIN
29 
30 template<class T, class DEL = std::default_delete<T> >
31 using UniquePtr = std::unique_ptr<T, DEL>;
32 template<class T>
33 using DefaultDelete = std::default_delete<T>;
34 
35 NLIB_NAMESPACE_END
36 #else
37 #include <algorithm>
38 
39 NLIB_NAMESPACE_BEGIN
40 
41 template<class T>
42 struct DefaultDelete {
43  void operator()(T* p) const NLIB_NOEXCEPT {
44  NLIB_STATIC_ASSERT(sizeof(T));
45  if (p) delete p;
46  }
47 };
48 
49 template<class T>
50 struct DefaultDelete<T[]> {
51  void operator()(T* p) const NLIB_NOEXCEPT {
52  NLIB_STATIC_ASSERT(sizeof(T));
53  if (p) delete[] p;
54  }
55 };
56 
57 NLIB_STATIC_ASSERT(IsEmpty<DefaultDelete<int> >::value&& IsEmpty<DefaultDelete<int[]> >::value);
58 
59 namespace detail {
60 
61 template<class T, class DEL, bool DEL_EMPTY>
62 class UniquePtrBase {
63  public:
64  UniquePtrBase() : ptr_(NULL), deleter_() {}
65  explicit UniquePtrBase(T* ptr) : ptr_(ptr), deleter_() {}
66  UniquePtrBase(T* ptr, const DEL& del) : ptr_(ptr), deleter_(del) {}
67 
68  protected:
69  DEL& get_deleter() { return deleter_; }
70  const DEL& get_deleter() const { return deleter_; }
71  T* ptr_;
72  DEL deleter_;
73  void Swap(UniquePtrBase& rhs) NLIB_NOEXCEPT {
74  using std::swap;
75  swap(this->ptr_, rhs.ptr_);
76  swap(this->deleter_, rhs.deleter_);
77  }
78  NLIB_DISALLOW_COPY_AND_ASSIGN(UniquePtrBase);
79 };
80 
81 template<class T, class DEL>
82 class UniquePtrBase<T, DEL, true> : public DEL {
83  public:
84  UniquePtrBase() : ptr_(NULL) {}
85  explicit UniquePtrBase(T* ptr) : ptr_(ptr) {}
86  UniquePtrBase(T* ptr, const DEL& del) : DEL(del), ptr_(ptr) {}
87 
88  protected:
89  DEL& get_deleter() { return *this; }
90  const DEL& get_deleter() const { return *this; }
91  T* ptr_;
92  void Swap(UniquePtrBase& rhs) NLIB_NOEXCEPT {
93  using std::swap;
94  swap(this->ptr_, rhs.ptr_);
95  }
96  NLIB_DISALLOW_COPY_AND_ASSIGN(UniquePtrBase);
97 };
98 
99 template<class S>
100 struct IsCompleteType : public IntegralConstant<bool, (sizeof(S) != 0 || sizeof(S) == 0)> {};
101 
102 template<>
103 struct IsCompleteType<void> : public TrueType {};
104 
105 } // namespace detail
106 
107 template<class T, class DEL = DefaultDelete<T> >
108 class UniquePtr NLIB_FINAL : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
109  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
110 
111  public:
112  typedef T* pointer_type; // simpler definition than std::unique_ptr
113  typedef DEL deleter_type; // note that DEL cannot have data members
114  typedef T element_type;
115 
116  NLIB_CEXPR UniquePtr() NLIB_NOEXCEPT : BaseType() {}
117  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
118  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
119  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
120  UniquePtr(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT : BaseType() { swap(rhs); }
121  UniquePtr& assign(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT {
122  UniquePtr tmp(release());
123  swap(rhs);
124  return *this;
125  }
126  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { this->Swap(rhs); }
128  NLIB_STATIC_ASSERT(detail::IsCompleteType<T>::value);
129  // typedef char is_complete_type[sizeof(T) ? 1 : -1];
130  // (void) sizeof(is_complete_type);
131  if (this->ptr_) get_deleter()(this->ptr_);
132  }
133  void reset(T* p = 0) NLIB_NOEXCEPT {
134  // NOTE:
135  // this->ptr_ is for CTR
136  if (p != this->ptr_) {
137  T* old = this->ptr_;
138  this->ptr_ = p;
139  if (old) get_deleter()(old);
140  }
141  }
142  typename AddRef<T>::type operator*() const {
143  NLIB_ASSERT(this->ptr_ != NULL);
144  return *this->ptr_;
145  }
146  T* operator->() const NLIB_NOEXCEPT {
147  NLIB_ASSERT(this->ptr_ != NULL);
148  return this->ptr_;
149  }
150  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
151  T* release() NLIB_NOEXCEPT {
152  T* p = this->ptr_;
153  this->ptr_ = NULL;
154  return p;
155  }
156  UniquePtr& operator=(nullptr_t) NLIB_NOEXCEPT {
157  this->reset();
158  return *this;
159  }
160  size_t GetHash() const { return Hash<T*>()(this->get()); }
161  DEL& get_deleter() { return BaseType::get_deleter(); }
162  const DEL& get_deleter() const { return BaseType::get_deleter(); }
163 
164  NLIB_SAFE_BOOL(UniquePtr, this->ptr_ != NULL);
165 
166  private:
167  template<class S, class D>
168  bool operator==(const UniquePtr<S, D>& p) const;
169  template<class S, class D>
170  bool operator!=(const UniquePtr<S, D>& p) const;
172 };
173 
174 template<class T, class DEL>
175 class UniquePtr<T[], DEL> : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
176  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
177 
178  public:
179  typedef T* pointer_type; // simpler definition than std::unique_ptr
180  typedef DEL deleter_type;
181  typedef T element_type;
182 
183  NLIB_CEXPR UniquePtr() NLIB_NOEXCEPT : BaseType() {}
184  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
185  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
186  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
187  UniquePtr(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT : BaseType() { swap(rhs); }
188  UniquePtr& assign(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT {
189  UniquePtr tmp(release());
190  swap(rhs);
191  return *this;
192  }
193  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { this->Swap(rhs); }
194  ~UniquePtr() NLIB_NOEXCEPT {
195  NLIB_STATIC_ASSERT(sizeof(T));
196  get_deleter()(this->ptr_);
197  }
198  void reset(T* p = 0) NLIB_NOEXCEPT {
199  // NOTE:
200  // this->ptr_ is for CTR
201  if (p != this->ptr_) {
202  T* old = this->ptr_;
203  this->ptr_ = p;
204  if (old) get_deleter()(old);
205  }
206  }
207  T& operator*() const {
208  NLIB_ASSERT(this->ptr_ != NULL);
209  return *this->ptr_;
210  }
211  T* operator->() const NLIB_NOEXCEPT {
212  NLIB_ASSERT(this->ptr_ != NULL);
213  return this->ptr_;
214  }
215  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
216  T* release() NLIB_NOEXCEPT {
217  T* p = this->ptr_;
218  this->ptr_ = NULL;
219  return p;
220  }
221  T& operator[](size_t n) { return get()[n]; }
222  const T& operator[](size_t n) const { return get()[n]; }
223  size_t GetHash() const { return Hash<T*>()(this->get()); }
224  DEL& get_deleter() { return BaseType::get_deleter(); }
225  const DEL& get_deleter() const { return BaseType::get_deleter(); }
226 
227  NLIB_SAFE_BOOL(UniquePtr, this->ptr_ != NULL);
228 
229  private:
230  template<class S, class D>
231  bool operator==(const UniquePtr<S, D>& p) const;
232  template<class S, class D>
233  bool operator!=(const UniquePtr<S, D>& p) const;
235 };
236 
237 template<class T1, class D1, class T2, class D2>
238 bool operator==(const UniquePtr<T1, D1>& rhs, const UniquePtr<T2, D2>& lhs) NLIB_NOEXCEPT {
239  return rhs.get() == lhs.get();
240 }
241 
242 template<class T1, class D1>
243 bool operator==(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
244  return !lhs;
245 }
246 
247 template<class T1, class D1>
248 bool operator==(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
249  return !rhs;
250 }
251 
252 template<class T1, class D1, class T2, class D2>
253 bool operator!=(const UniquePtr<T1, D1>& rhs, const UniquePtr<T2, D2>& lhs) NLIB_NOEXCEPT {
254  return rhs.get() != lhs.get();
255 }
256 
257 template<class T1, class D1>
258 bool operator!=(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
259  return static_cast<bool>(lhs);
260 }
261 
262 template<class T1, class D1>
263 bool operator!=(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
264  return static_cast<bool>(rhs);
265 }
266 
267 NLIB_NAMESPACE_END
268 
269 NLIB_DEFINE_STD_SWAP_T_BEGIN2(nn, nlib)
270 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::UniquePtr)
271 NLIB_DEFINE_STD_SWAP_T_END2(nn, nlib)
272 
273 NLIB_DEFINE_STD_HASH_BEGIN2(nn, nlib)
274 NLIB_DEFINE_STD_HASH_T2(T, DEL, NLIB_NS::UniquePtr)
275 NLIB_DEFINE_STD_HASH_END2(nn, nlib)
276 
277 #endif
278 
279 NLIB_NAMESPACE_BEGIN
280 
281 /*
282 template<class T, void FreeFunc(void*) = free>
283 struct FreeDeleterT {
284  void operator()(T* p) const NLIB_NOEXCEPT {
285  NLIB_STATIC_ASSERT(sizeof(T));
286  NLIB_STATIC_ASSERT(IsPod<T>::value);
287  if (p) FreeFunc(p);
288  }
289 };
290 */
291 
292 namespace detail {
293 
294 template<class T, class ALLOC, bool DEL_EMPTY>
295 class DefaultDeleteExBase {
296  public:
297  DefaultDeleteExBase() : al() {}
298  explicit DefaultDeleteExBase(const ALLOC& al_) : al(al_) {}
299 
300  protected:
301  ALLOC& get_allocator() { return al; }
302  ALLOC al;
303 
304  private:
305  NLIB_DISALLOW_COPY_AND_ASSIGN(DefaultDeleteExBase);
306 };
307 
308 template<class T, class ALLOC>
309 class DefaultDeleteExBase<T, ALLOC, true> : public ALLOC {
310  public:
311  DefaultDeleteExBase() {}
312  explicit DefaultDeleteExBase(const ALLOC& al_) { NLIB_UNUSED(al_); }
313 
314  protected:
315  ALLOC& get_allocator() { return *this; }
316 };
317 
318 } // namespace detail
319 
320 template<class T, class ALLOC = std::allocator<T> >
321 struct DefaultDeleteEx : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
322  void operator()(T* p) NLIB_NOEXCEPT {
323  NLIB_STATIC_ASSERT(sizeof(T));
324  NLIB_STATIC_ASSERT(!IsArray<T>::value);
325  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
326  if (p) {
327  ALLOC& al = BaseType::get_allocator();
328  al.destroy(p);
329  al.deallocate(p, 1);
330  }
331  }
332 };
333 
334 template<class T, class ALLOC>
335 struct DefaultDeleteEx<T[], ALLOC>
336  : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
337  // mainly for using malloc variant like nmalloc
338  // ex.
339  // UniquePtr<
340  // unsigned char[],
341  // DefaultDeleteEx<unsigned char[], NMallocStlAllocator<unsigned char> >
342  // >
343  void operator()(T* p) NLIB_NOEXCEPT {
344  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
345  NLIB_STATIC_ASSERT(sizeof(T));
346  NLIB_STATIC_ASSERT(IsPod<T>::value);
347  if (p) {
348  ALLOC& al = BaseType::get_allocator();
349  // The length is unknown
350  al.deallocate(p, 1);
351  }
352  }
353 };
354 
355 NLIB_NAMESPACE_END
356 
357 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
358 template<class T, class DEL>
359 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&) = delete;
360 #else
361 template<class T, class DEL>
362 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&);
363 #endif
364 
365 #endif // INCLUDE_NN_NLIB_UNIQUEPTR_H_
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
#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:183
#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:199
Definition: Base64.h:25
In the C++11 environment (which supports alias templates), std::unique_ptr is made an alias template...
Definition: UniquePtr.h:108
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are equal.
Definition: NMalloc.h:130
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:135
An empty structure indicating that an argument to a function needs to be moved.
Definition: Config.h:270
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:109
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:111
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:195
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:250
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:174
bool nlib_is_error(const T &obj) noexcept
Returns true when the process result or object status is in an erroneous condition.
Definition: Config.h:658