nlib
UniquePtr.h
[詳解]
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() : ptr_(NULL), deleter_() {}
52  explicit UniquePtrBase(T* ptr) : ptr_(ptr), deleter_() {}
53  UniquePtrBase(T* ptr, const DEL& del) : ptr_(ptr), deleter_(del) {}
54 
55  protected:
56  DEL& get_deleter() { return deleter_; }
57  const DEL& get_deleter() const { return deleter_; }
58  T* ptr_;
59  DEL deleter_;
60  void Swap(UniquePtrBase& rhs) NLIB_NOEXCEPT { // NOLINT
61  using std::swap;
62  swap(this->ptr_, rhs.ptr_);
63  swap(this->deleter_, rhs.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() : ptr_(NULL) {}
72  explicit UniquePtrBase(T* ptr) : ptr_(ptr) {}
73  UniquePtrBase(T* ptr, const DEL& del) : DEL(del), ptr_(ptr) {}
74 
75  protected:
76  DEL& get_deleter() { return *this; }
77  const DEL& get_deleter() const { return *this; }
78  T* ptr_;
79  void Swap(UniquePtrBase& rhs) NLIB_NOEXCEPT { // NOLINT
80  using std::swap;
81  swap(this->ptr_, rhs.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->ptr_) get_deleter()(this->ptr_);
114  }
115  void reset(T* p = 0) NLIB_NOEXCEPT {
116  // NOTE:
117  // this->ptr_ is for CTR
118  if (p != this->ptr_) {
119  T* old = this->ptr_;
120  this->ptr_ = p;
121  if (old) get_deleter()(old);
122  }
123  }
124  typename AddRef<T>::type operator*() const {
125  NLIB_ASSERT(this->ptr_ != NULL);
126  return *this->ptr_;
127  }
129  NLIB_ASSERT(this->ptr_ != NULL);
130  return this->ptr_;
131  }
132  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
134  T* p = this->ptr_;
135  this->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->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)
174  NLIB_STATIC_ASSERT(sizeof(T));
175  get_deleter()(this->ptr_);
176  }
177  void reset(T* p = 0) NLIB_NOEXCEPT {
178  // NOTE:
179  // this->ptr_ is for CTR
180  if (p != this->ptr_) {
181  T* old = this->ptr_;
182  this->ptr_ = p;
183  if (old) get_deleter()(old);
184  }
185  }
186  T& operator*() const {
187  NLIB_ASSERT(this->ptr_ != NULL);
188  return *this->ptr_;
189  }
190  T* operator->() const NLIB_NOEXCEPT {
191  NLIB_ASSERT(this->ptr_ != NULL);
192  return this->ptr_;
193  }
194  T* get() const NLIB_NOEXCEPT { return this->ptr_; }
195  T* release() NLIB_NOEXCEPT {
196  T* p = this->ptr_;
197  this->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->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 #ifdef NLIB_CXX11_DEFAULTED_AND_DELETED_FUNCTIONS
360 template<class T, class DEL>
361 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&) = delete;
362 #else
363 template<class T, class DEL>
364 bool nlib_is_error(NLIB_NS::UniquePtr<T, DEL>&);
365 #endif
366 
367 #endif // INCLUDE_NN_NLIB_UNIQUEPTR_H_
~UniquePtr() noexcept
デストラクタです。ポインタがNULLでなければデリータを実行して削除します。
Definition: UniquePtr.h:109
UniquePtr(T *p) noexcept
ポインタを設定します。
Definition: UniquePtr.h:106
C++11の標準ヘッダとなるtype_traitsの代用定義です。 コンパイラや標準ライブラリによってサポートされてい...
DEL & get_deleter()
デリータを取得します。
Definition: UniquePtr.h:146
constexpr UniquePtr(nullptr_t) noexcept
引数にnullptrを与えた場合に呼び出されます。
Definition: UniquePtr.h:105
#define NLIB_DISALLOW_COPY_AND_ASSIGN(TypeName)
TypeName で指定されたクラスのコピーコンストラクタと代入演算子を禁止します。
Definition: Config.h:145
#define NLIB_SAFE_BOOL(class_name, exp)
クラス内に安全なoperator bool()を定義します。 可能であればC++11のexplicit boolを利用します。 ...
Definition: Config.h:160
STL namespace
T element_type
Tがtypedefされています。
Definition: UniquePtr.h:102
UniquePtrはポインタの所有権を保持し、UniquePtrがスコープから出るときにデストラクタでポインタをDELで指...
Definition: UniquePtr.h:96
bool operator==(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価ならば、trueを返します。
Definition: NMalloc.h:110
bool operator!=(const HeapHash &rhs, const HeapHash &lhs)
2つのサマリを比較して等価でなければ、trueを返します。
Definition: NMalloc.h:115
void reset(T *p=0) noexcept
ポインタを置き換えます。置き換えられたポインタは削除されます。
Definition: UniquePtr.h:115
constexpr UniquePtr() noexcept
デフォルトコンストラクタです。
Definition: UniquePtr.h:104
size_t GetHash() const
ポインタに対してハッシュ値の計算を行い、計算結果を返します。
Definition: UniquePtr.h:145
UniquePtr & operator=(nullptr_t) noexcept
nullptrを代入します。
Definition: UniquePtr.h:141
AddRef< T >::type operator*() const
ポインタの参照外しを行います。
Definition: UniquePtr.h:124
void swap(UniquePtr &rhs) noexcept
格納されているポインタをスワップします。
Definition: UniquePtr.h:138
T * operator->() const noexcept
ポインタを返します。
Definition: UniquePtr.h:128
DEL deleter_type
DELがtypedefされています。
Definition: UniquePtr.h:101
const DEL & get_deleter() const
デリータを取得します。
Definition: UniquePtr.h:147
#define NLIB_NOEXCEPT
環境に合わせてnoexcept 又は同等の定義がされます。
Definition: Config.h:86
#define NLIB_CEXPR
利用可能であればconstexprが定義されます。そうでない場合は空文字列です。
Definition: Config.h:80
開発環境別の設定が書かれるファイルです。
TimeSpan operator*(int i, const TimeSpan &rhs) noexcept
rhs を i 倍します。
Definition: DateTime.h:212
UniquePtr(T *p, const DEL &del)
ポインタとデリータを設定します。
Definition: UniquePtr.h:107
#define NLIB_FINAL
利用可能であればfinalが定義されます。そうでない場合は空文字列です。
Definition: Config.h:211
#define NLIB_STATIC_ASSERT(exp)
静的アサートが定義されます。利用可能であればstatic_assertを利用します。
Definition: Config.h:136
T * pointer_type
T*がtypedefされています。
Definition: UniquePtr.h:100
bool nlib_is_error(const T &obj) noexcept
処理の結果やオブジェクトの状態がエラーである場合にtrueを返します。
Definition: Config.h:922
T * release() noexcept
ポインタの所有権を手放し、ポインタを返します。
Definition: UniquePtr.h:133