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(NLIB_CXX11_TEMPLATE_ALIAS)
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> // NOLINT
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); // NOLINT
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 { // NOLINT
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 { // NOLINT
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
101  : public IntegralConstant<bool, (sizeof(S) != 0 || sizeof(S) == 0)> {};
102 
103 template<>
104 struct IsCompleteType<void> : public TrueType {};
105 
106 } // namespace detail
107 
108 template <class T, class DEL = DefaultDelete<T> >
109 class UniquePtr NLIB_FINAL : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
110  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
111 
112  public:
113  typedef T* pointer_type; // simpler definition than std::unique_ptr
114  typedef DEL deleter_type; // note that DEL cannot have data members
115  typedef T element_type;
116 
118  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
119  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
120  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
121  NLIB_MOVE_MEMBER_HELPER_1(UniquePtr, BaseType)
123  NLIB_STATIC_ASSERT(detail::IsCompleteType<T>::value);
124  // typedef char is_complete_type[sizeof(T) ? 1 : -1];
125  // (void) sizeof(is_complete_type);
126  if (this->ptr_) get_deleter()(this->ptr_);
127  }
128  void reset(T* p = 0) NLIB_NOEXCEPT {
129  // NOTE:
130  // this->ptr_ is for CTR
131  if (p != this->ptr_) {
132  T* old = this->ptr_;
133  this->ptr_ = p;
134  if (old) get_deleter()(old);
135  }
136  }
137  typename AddRef<T>::type operator*() const {
138  NLIB_ASSERT(this->ptr_ != NULL);
139  return *this->ptr_;
140  }
142  NLIB_ASSERT(this->ptr_ != NULL);
143  return this->ptr_;
144  }
145  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
147  T* p = this->ptr_;
148  this->ptr_ = NULL;
149  return p;
150  }
151  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { // NOLINT
152  this->Swap(rhs);
153  }
155  this->reset();
156  return *this;
157  }
158  size_t GetHash() const { return Hash<T*>()(this->get()); }
159  DEL& get_deleter() { return BaseType::get_deleter(); }
160  const DEL& get_deleter() const { return BaseType::get_deleter(); }
161 
162  NLIB_SAFE_BOOL(UniquePtr, this->ptr_ != NULL);
163 
164  private:
165  template <class S, class D>
166  bool operator==(const UniquePtr<S, D>& p) const;
167  template <class S, class D>
168  bool operator!=(const UniquePtr<S, D>& p) const;
170 };
171 
172 template <class T, class DEL>
173 class UniquePtr<T[], DEL> : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
174  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
175 
176  public:
177  typedef T* pointer_type; // simpler definition than std::unique_ptr
178  typedef DEL deleter_type;
179  typedef T element_type;
180 
181  NLIB_CEXPR UniquePtr() NLIB_NOEXCEPT : BaseType() {}
182  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
183  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
184  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
185  NLIB_MOVE_MEMBER_HELPER_1(UniquePtr, BaseType)
187  NLIB_STATIC_ASSERT(sizeof(T));
188  get_deleter()(this->ptr_);
189  }
190  void reset(T* p = 0) NLIB_NOEXCEPT {
191  // NOTE:
192  // this->ptr_ is for CTR
193  if (p != this->ptr_) {
194  T* old = this->ptr_;
195  this->ptr_ = p;
196  if (old) get_deleter()(old);
197  }
198  }
199  T& operator*() const {
200  NLIB_ASSERT(this->ptr_ != NULL);
201  return *this->ptr_;
202  }
203  T* operator->() const NLIB_NOEXCEPT {
204  NLIB_ASSERT(this->ptr_ != NULL);
205  return this->ptr_;
206  }
207  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
208  T* release() NLIB_NOEXCEPT {
209  T* p = this->ptr_;
210  this->ptr_ = NULL;
211  return p;
212  }
213  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { // NOLINT
214  this->Swap(rhs);
215  }
216  T& operator[](size_t n) { return get()[n]; }
217  const T& operator[](size_t n) const { return get()[n]; }
218  size_t GetHash() const { return Hash<T*>()(this->get()); }
219  DEL& get_deleter() { return BaseType::get_deleter(); }
220  const DEL& get_deleter() const { return BaseType::get_deleter(); }
221 
222  NLIB_SAFE_BOOL(UniquePtr, this->ptr_ != NULL);
223 
224  private:
225  template <class S, class D>
226  bool operator==(const UniquePtr<S, D>& p) const;
227  template <class S, class D>
228  bool operator!=(const UniquePtr<S, D>& p) const;
230 };
231 
232 template <class T1, class D1, class T2, class D2>
234  return rhs.get() == lhs.get();
235 }
236 
237 template <class T1, class D1>
238 bool operator==(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
239  return !lhs;
240 }
241 
242 template <class T1, class D1>
243 bool operator==(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
244  return !rhs;
245 }
246 
247 template <class T1, class D1, class T2, class D2>
249  return rhs.get() != lhs.get();
250 }
251 
252 template <class T1, class D1>
253 bool operator!=(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
254  return static_cast<bool>(lhs);
255 }
256 
257 template <class T1, class D1>
258 bool operator!=(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
259  return static_cast<bool>(rhs);
260 }
261 
262 NLIB_NAMESPACE_END
263 
264 #ifndef NLIB_STD_SWAP_WORKAROUND
265 NLIB_NAMESPACE_BEGIN
266 #else
267 NLIB_DEFINE_STD_SWAP_T_BEGIN1(std) // NOLINT
268 #endif
269 
270 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::UniquePtr) // NOLINT
271 
272 #ifndef NLIB_STD_SWAP_WORKAROUND
273 NLIB_NAMESPACE_END
274 #else
275 NLIB_DEFINE_STD_SWAP_T_END1(std) // NOLINT
276 #endif
277 
278 #ifndef NLIB_CXX11_TEMPLATE_ALIAS
279 NLIB_NAMESPACE_BEGIN
280 #else
281 NLIB_DEFINE_STD_HASH_T_BEGIN1(std) // NOLINT
282 #endif
283 
284 NLIB_DEFINE_STD_HASH_T2(T, DEL, NLIB_NS::UniquePtr) // NOLINT
285 
286 #ifndef NLIB_CXX11_TEMPLATE_ALIAS
287 NLIB_NAMESPACE_END
288 #else
289 NLIB_DEFINE_STD_HASH_T_END1(std) // NOLINT
290 #endif
291 
292 #endif
293 
294 NLIB_NAMESPACE_BEGIN
295 
296 /*
297 template<class T, void FreeFunc(void*) = free>
298 struct FreeDeleterT {
299  void operator()(T* p) const NLIB_NOEXCEPT {
300  NLIB_STATIC_ASSERT(sizeof(T));
301  NLIB_STATIC_ASSERT(IsPod<T>::value);
302  if (p) FreeFunc(p);
303  }
304 };
305 */
306 
307 namespace detail {
308 
309 template <class T, class ALLOC, bool DEL_EMPTY>
310 class DefaultDeleteExBase {
311  public:
312  DefaultDeleteExBase() : al() {}
313  explicit DefaultDeleteExBase(const ALLOC& al_) : al(al_) {}
314 
315  protected:
316  ALLOC& get_allocator() { return al; }
317  ALLOC al;
318 
319  private:
320  NLIB_DISALLOW_COPY_AND_ASSIGN(DefaultDeleteExBase);
321 };
322 
323 template <class T, class ALLOC>
324 class DefaultDeleteExBase<T, ALLOC, true> : public ALLOC {
325  public:
326  DefaultDeleteExBase() {}
327  explicit DefaultDeleteExBase(const ALLOC& al_) { NLIB_UNUSED(al_); }
328 
329  protected:
330  ALLOC& get_allocator() { return *this; }
331 };
332 
333 } // namespace detail
334 
335 template <class T, class ALLOC = std::allocator<T> >
336 struct DefaultDeleteEx : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
337  void operator()(T* p)NLIB_NOEXCEPT {
338  NLIB_STATIC_ASSERT(sizeof(T));
339  NLIB_STATIC_ASSERT(!IsArray<T>::value);
340  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
341  if (p) {
342  ALLOC& al = BaseType::get_allocator();
343  al.destroy(p);
344  al.deallocate(p, 1);
345  }
346  }
347 };
348 
349 template <class T, class ALLOC>
350 struct DefaultDeleteEx<T[], ALLOC>
351  : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
352  // mainly for using malloc variant like nmalloc
353  // ex.
354  // UniquePtr<
355  // unsigned char[],
356  // DefaultDeleteEx<unsigned char[], NMallocStlAllocator<unsigned char> >
357  // >
358  void operator()(T* p)NLIB_NOEXCEPT {
359  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
360  NLIB_STATIC_ASSERT(sizeof(T));
361  NLIB_STATIC_ASSERT(IsPod<T>::value);
362  if (p) {
363  ALLOC& al = BaseType::get_allocator();
364  // The length is unknown
365  al.deallocate(p, 1);
366  }
367  }
368 };
369 
370 NLIB_NAMESPACE_END
371 
372 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
373 template<class T, class DEL>
374 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&) = delete;
375 #else
376 template<class T, class DEL>
377 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&);
378 #endif
379 
380 #endif // INCLUDE_NN_NLIB_UNIQUEPTR_H_
~UniquePtr() noexcept
Destructor. If the pointer is not NULL, executes the deleter and deletes.
Definition: UniquePtr.h:122
UniquePtr(T *p) noexcept
Sets a pointer.
Definition: UniquePtr.h:119
Substitute definitions for the C++11 standard header type_traits. These substitute definitions are us...
DEL & get_deleter()
Gets the deleter.
Definition: UniquePtr.h:159
constexpr UniquePtr(nullptr_t) noexcept
This function is called if nullptr has been passed to a parameter.
Definition: UniquePtr.h:118
#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:163
#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:178
STL namespace.
T element_type
Defines T using typedef.
Definition: UniquePtr.h:115
UniquePtr owns the pointer, and when it goes out of scope, the pointer is released by the destructor ...
Definition: UniquePtr.h:109
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are equal.
Definition: NMalloc.h:145
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:150
void reset(T *p=0) noexcept
Replaces a pointer. The replaced pointer is deleted.
Definition: UniquePtr.h:128
constexpr UniquePtr() noexcept
Instantiates the object with default parameters (default constructor).
Definition: UniquePtr.h:117
size_t GetHash() const
Computes the hash value for the pointer and returns the calculation result.
Definition: UniquePtr.h:158
UniquePtr & operator=(nullptr_t) noexcept
Substitutes for nullptr.
Definition: UniquePtr.h:154
AddRef< T >::type operator*() const
Dereferences the pointer.
Definition: UniquePtr.h:137
void swap(UniquePtr &rhs) noexcept
Swaps the pointer that is being stored.
Definition: UniquePtr.h:151
T * operator->() const noexcept
Returns the pointer.
Definition: UniquePtr.h:141
DEL deleter_type
Defines DEL using typedef.
Definition: UniquePtr.h:114
const DEL & get_deleter() const
Gets the deleter.
Definition: UniquePtr.h:160
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:99
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:93
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:225
UniquePtr(T *p, const DEL &del)
Sets a pointer and a deleter.
Definition: UniquePtr.h:120
#define NLIB_FINAL
Defines final if it is available for use. If not, holds an empty string.
Definition: Config.h:229
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:154
T * pointer_type
Defines T* using typedef.
Definition: UniquePtr.h:113
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:768
T * release() noexcept
Release ownership of the pointer and returns the pointer.
Definition: UniquePtr.h:146