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> // 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  UniquePtr(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT : BaseType() { swap(rhs); }
123  UniquePtr tmp(release());
124  swap(rhs);
125  return *this;
126  }
127  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { // NOLINT
128  this->Swap(rhs);
129  }
131  NLIB_STATIC_ASSERT(detail::IsCompleteType<T>::value);
132  // typedef char is_complete_type[sizeof(T) ? 1 : -1];
133  // (void) sizeof(is_complete_type);
134  if (this->ptr_) get_deleter()(this->ptr_);
135  }
136  void reset(T* p = 0) NLIB_NOEXCEPT {
137  // NOTE:
138  // this->ptr_ is for CTR
139  if (p != this->ptr_) {
140  T* old = this->ptr_;
141  this->ptr_ = p;
142  if (old) get_deleter()(old);
143  }
144  }
145  typename AddRef<T>::type operator*() const {
146  NLIB_ASSERT(this->ptr_ != NULL);
147  return *this->ptr_;
148  }
150  NLIB_ASSERT(this->ptr_ != NULL);
151  return this->ptr_;
152  }
153  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
155  T* p = this->ptr_;
156  this->ptr_ = NULL;
157  return p;
158  }
160  this->reset();
161  return *this;
162  }
163  size_t GetHash() const { return Hash<T*>()(this->get()); }
164  DEL& get_deleter() { return BaseType::get_deleter(); }
165  const DEL& get_deleter() const { return BaseType::get_deleter(); }
166 
167  NLIB_SAFE_BOOL(UniquePtr, this->ptr_ != NULL);
168 
169  private:
170  template <class S, class D>
171  bool operator==(const UniquePtr<S, D>& p) const;
172  template <class S, class D>
173  bool operator!=(const UniquePtr<S, D>& p) const;
175 };
176 
177 template <class T, class DEL>
178 class UniquePtr<T[], DEL> : public detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> {
179  typedef detail::UniquePtrBase<T, DEL, IsEmpty<DEL>::value> BaseType;
180 
181  public:
182  typedef T* pointer_type; // simpler definition than std::unique_ptr
183  typedef DEL deleter_type;
184  typedef T element_type;
185 
186  NLIB_CEXPR UniquePtr() NLIB_NOEXCEPT : BaseType() {}
187  NLIB_CEXPR explicit UniquePtr(nullptr_t) NLIB_NOEXCEPT : BaseType() {}
188  explicit UniquePtr(T* p) NLIB_NOEXCEPT : BaseType(p) {}
189  UniquePtr(T* p, const DEL& del) : BaseType(p, del) {}
190  UniquePtr(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT : BaseType() { swap(rhs); }
191  UniquePtr& assign(UniquePtr& rhs, move_tag) NLIB_NOEXCEPT {
192  UniquePtr tmp(release());
193  swap(rhs);
194  return *this;
195  }
196  void swap(UniquePtr& rhs) NLIB_NOEXCEPT { // NOLINT
197  this->Swap(rhs);
198  }
200  NLIB_STATIC_ASSERT(sizeof(T));
201  get_deleter()(this->ptr_);
202  }
203  void reset(T* p = 0) NLIB_NOEXCEPT {
204  // NOTE:
205  // this->ptr_ is for CTR
206  if (p != this->ptr_) {
207  T* old = this->ptr_;
208  this->ptr_ = p;
209  if (old) get_deleter()(old);
210  }
211  }
212  T& operator*() const {
213  NLIB_ASSERT(this->ptr_ != NULL);
214  return *this->ptr_;
215  }
216  T* operator->() const NLIB_NOEXCEPT {
217  NLIB_ASSERT(this->ptr_ != NULL);
218  return this->ptr_;
219  }
220  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
221  T* release() NLIB_NOEXCEPT {
222  T* p = this->ptr_;
223  this->ptr_ = NULL;
224  return p;
225  }
226  T& operator[](size_t n) { return get()[n]; }
227  const T& operator[](size_t n) const { return get()[n]; }
228  size_t GetHash() const { return Hash<T*>()(this->get()); }
229  DEL& get_deleter() { return BaseType::get_deleter(); }
230  const DEL& get_deleter() const { return BaseType::get_deleter(); }
231 
232  NLIB_SAFE_BOOL(UniquePtr, this->ptr_ != NULL);
233 
234  private:
235  template <class S, class D>
236  bool operator==(const UniquePtr<S, D>& p) const;
237  template <class S, class D>
238  bool operator!=(const UniquePtr<S, D>& p) const;
240 };
241 
242 template <class T1, class D1, class T2, class D2>
244  return rhs.get() == lhs.get();
245 }
246 
247 template <class T1, class D1>
248 bool operator==(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
249  return !lhs;
250 }
251 
252 template <class T1, class D1>
253 bool operator==(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
254  return !rhs;
255 }
256 
257 template <class T1, class D1, class T2, class D2>
259  return rhs.get() != lhs.get();
260 }
261 
262 template <class T1, class D1>
263 bool operator!=(const UniquePtr<T1, D1>& lhs, nullptr_t) NLIB_NOEXCEPT {
264  return static_cast<bool>(lhs);
265 }
266 
267 template <class T1, class D1>
268 bool operator!=(nullptr_t, const UniquePtr<T1, D1>& rhs) NLIB_NOEXCEPT {
269  return static_cast<bool>(rhs);
270 }
271 
272 NLIB_NAMESPACE_END
273 
274 NLIB_DEFINE_STD_SWAP_T_BEGIN2(nn, nlib)
275 NLIB_DEFINE_STD_SWAP_T2(T, DEL, NLIB_NS::UniquePtr) // NOLINT
276 NLIB_DEFINE_STD_SWAP_T_END2(nn, nlib)
277 
278 NLIB_DEFINE_STD_HASH_BEGIN2(nn, nlib)
279 NLIB_DEFINE_STD_HASH_T2(T, DEL, NLIB_NS::UniquePtr) // NOLINT
280 NLIB_DEFINE_STD_HASH_END2(nn, nlib)
281 
282 #endif
283 
284 NLIB_NAMESPACE_BEGIN
285 
286 /*
287 template<class T, void FreeFunc(void*) = free>
288 struct FreeDeleterT {
289  void operator()(T* p) const NLIB_NOEXCEPT {
290  NLIB_STATIC_ASSERT(sizeof(T));
291  NLIB_STATIC_ASSERT(IsPod<T>::value);
292  if (p) FreeFunc(p);
293  }
294 };
295 */
296 
297 namespace detail {
298 
299 template <class T, class ALLOC, bool DEL_EMPTY>
300 class DefaultDeleteExBase {
301  public:
302  DefaultDeleteExBase() : al() {}
303  explicit DefaultDeleteExBase(const ALLOC& al_) : al(al_) {}
304 
305  protected:
306  ALLOC& get_allocator() { return al; }
307  ALLOC al;
308 
309  private:
310  NLIB_DISALLOW_COPY_AND_ASSIGN(DefaultDeleteExBase);
311 };
312 
313 template <class T, class ALLOC>
314 class DefaultDeleteExBase<T, ALLOC, true> : public ALLOC {
315  public:
316  DefaultDeleteExBase() {}
317  explicit DefaultDeleteExBase(const ALLOC& al_) { NLIB_UNUSED(al_); }
318 
319  protected:
320  ALLOC& get_allocator() { return *this; }
321 };
322 
323 } // namespace detail
324 
325 template <class T, class ALLOC = std::allocator<T> >
326 struct DefaultDeleteEx : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
327  void operator()(T* p)NLIB_NOEXCEPT {
328  NLIB_STATIC_ASSERT(sizeof(T));
329  NLIB_STATIC_ASSERT(!IsArray<T>::value);
330  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
331  if (p) {
332  ALLOC& al = BaseType::get_allocator();
333  al.destroy(p);
334  al.deallocate(p, 1);
335  }
336  }
337 };
338 
339 template <class T, class ALLOC>
340 struct DefaultDeleteEx<T[], ALLOC>
341  : public detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> {
342  // mainly for using malloc variant like nmalloc
343  // ex.
344  // UniquePtr<
345  // unsigned char[],
346  // DefaultDeleteEx<unsigned char[], NMallocStlAllocator<unsigned char> >
347  // >
348  void operator()(T* p)NLIB_NOEXCEPT {
349  typedef detail::DefaultDeleteExBase<T, ALLOC, IsEmpty<ALLOC>::value> BaseType;
350  NLIB_STATIC_ASSERT(sizeof(T));
351  NLIB_STATIC_ASSERT(IsPod<T>::value);
352  if (p) {
353  ALLOC& al = BaseType::get_allocator();
354  // The length is unknown
355  al.deallocate(p, 1);
356  }
357  }
358 };
359 
360 NLIB_NAMESPACE_END
361 
362 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
363 template<class T, class DEL>
364 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&) = delete;
365 #else
366 template<class T, class DEL>
367 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&);
368 #endif
369 
370 #endif // INCLUDE_NN_NLIB_UNIQUEPTR_H_
~UniquePtr() noexcept
Destructor. If the pointer is not NULL, executes the deleter and deletes.
Definition: UniquePtr.h:130
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...
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:179
#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:194
Definition: Base64.h:25
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:149
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
Returns true if the two compared summaries are not equal.
Definition: NMalloc.h:154
void reset(T *p=0) noexcept
Replaces a pointer. The replaced pointer is deleted.
Definition: UniquePtr.h:136
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:163
UniquePtr & operator=(nullptr_t) noexcept
Substitutes for nullptr.
Definition: UniquePtr.h:159
AddRef< T >::type operator*() const
Dereferences the pointer.
Definition: UniquePtr.h:145
An empty structure indicating that an argument to a function needs to be moved.
Definition: Config.h:265
void swap(UniquePtr &rhs) noexcept
Swaps the pointer that is being stored.
Definition: UniquePtr.h:127
T * operator->() const noexcept
Returns the pointer.
Definition: UniquePtr.h:149
DefaultDelete< FutureTuple< R1, R2 > > deleter_type
Defines DEL using typedef.
Definition: UniquePtr.h:114
#define NLIB_NOEXCEPT
Defines noexcept geared to the environment, or the equivalent.
Definition: Config.h:105
#define NLIB_CEXPR
Defines constexpr if it is available for use. If not, holds an empty string.
Definition: Config.h:107
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:210
UniquePtr & assign(UniquePtr &rhs, move_tag) noexcept
Assigns a value through a move operation.
Definition: UniquePtr.h:122
UniquePtr(UniquePtr &rhs, move_tag) noexcept
Builds an object through a move operation.
Definition: UniquePtr.h:121
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:245
#define NLIB_STATIC_ASSERT(exp)
Defines a static assertion. Uses static_assert if it is available for use.
Definition: Config.h:170
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:682
T * release() noexcept
Release ownership of the pointer and returns the pointer.
Definition: UniquePtr.h:154