1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
// Copyright 2009 Howard Hinnant, Ion Gaztañaga.
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// See http://www.boost.org/libs/foreach for documentation
// This is a C++03 emulation of std::unique_ptr placed in namespace boost.
// Reference http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2800.pdf
// for the latest unique_ptr specification, and
// reference http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html
// for any pending issues against this specification.
#ifndef BUTIL_UNIQUE_PTR_H
#define BUTIL_UNIQUE_PTR_H
#include "butil/build_config.h"
#if defined(BUTIL_CXX11_ENABLED)
#include <memory> // std::unique_ptr
#elif !defined(BAIDU_NO_EMULATED_UNIQUE_PTR)
#include <algorithm> // std::swap until C++11
#include "butil/type_traits.h"
#include "butil/macros.h" // BAIDU_CASSERT
namespace std {
namespace up_detail {
typedef char one;
struct two {one _[2];};
// An is_convertible<From, To> that considers From an rvalue (consistent with C++0X).
// This is a simplified version neglecting the types function, array, void and abstract types
// I had to make a special case out of is_convertible<T,T> to make move-only
// types happy.
namespace is_conv_imp {
template <class T> one test1(const T&);
template <class T> two test1(...);
template <class T> one test2(T);
template <class T> two test2(...);
template <class T> T source();
}
template <class T1, class T2>
struct is_convertible {
static const bool value = sizeof(is_conv_imp::test1<T2>(is_conv_imp::source<T1>())) == 1;
};
template <class T>
struct is_convertible<T, T> {
static const bool value = sizeof(is_conv_imp::test2<T>(is_conv_imp::source<T>())) == 1;
};
template <class T>
class rv {
T& r_;
public:
explicit rv(T& r) : r_(r) {}
T* operator->() {return &r_;}
T& operator*() {return r_;}
};
template <class T>
struct identity {
typedef T type;
};
} // up_detail
template <class T>
inline
typename butil::enable_if<
!up_detail::is_convertible<T, up_detail::rv<T> >::value,
T&
>::type
move(T& t) {
return t;
}
template <class T>
inline
typename butil::enable_if <
!up_detail::is_convertible<T, up_detail::rv<T> >::value,
const T&
>::type
move(const T& t) {
return t;
}
template <class T>
inline
typename butil::enable_if <
up_detail::is_convertible<T, up_detail::rv<T> >::value,
T
>::type
move(T& t) {
return T(up_detail::rv<T>(t));
}
template <class T>
inline
typename butil::enable_if <
butil::is_reference<T>::value,
T
>::type
forward(typename up_detail::identity<T>::type t) {
return t;
}
template <class T>
inline
typename butil::enable_if <
!butil::is_reference<T>::value,
T
>::type
forward(typename up_detail::identity<T>::type& t) {
return move(t);
}
template <class T>
inline
typename butil::enable_if <
!butil::is_reference<T>::value,
T
>::type
forward(const typename up_detail::identity<T>::type& t) {
return move(const_cast<T&>(t));
}
namespace up_detail {
// A move-aware but stripped-down compressed_pair which only optimizes storage for T2
template <class T1, class T2, bool = butil::is_empty<T2>::value>
class UniquePtrStorage {
T1 t1_;
T2 t2_;
typedef typename butil::add_reference<T2>::type T2_reference;
typedef typename butil::add_reference<const T2>::type T2_const_reference;
UniquePtrStorage(const UniquePtrStorage&);
UniquePtrStorage& operator=(const UniquePtrStorage&);
public:
operator rv<UniquePtrStorage>() {return rv<UniquePtrStorage>(*this);}
UniquePtrStorage() : t1_(), t2_() {}
explicit UniquePtrStorage(T1 t1) : t1_(move(t1)), t2_() {}
UniquePtrStorage(T1 t1, T2 t2) : t1_(move(t1)), t2_(forward<T2>(t2)) {}
T1& first() {return t1_;}
const T1& first() const {return t1_;}
T2_reference second() {return t2_;}
T2_const_reference second() const {return t2_;}
};
template <class T1, class T2>
class UniquePtrStorage<T1, T2, true> : private T2 {
T1 t1_;
typedef T2 t2_;
UniquePtrStorage(const UniquePtrStorage&);
UniquePtrStorage& operator=(const UniquePtrStorage&);
public:
operator rv<UniquePtrStorage>() {return rv<UniquePtrStorage>(*this);}
UniquePtrStorage() : t1_() {}
explicit UniquePtrStorage(T1 t1) : t1_(move(t1)) {}
UniquePtrStorage(T1 t1, T2 t2) : t2_(move(t2)), t1_(move(t1)) {}
T1& first() {return t1_;}
const T1& first() const {return t1_;}
T2& second() {return *this;}
const T2& second() const {return *this;}
};
template <class T1, class T2, bool b>
inline
void
swap(UniquePtrStorage<T1, T2, b>& x, UniquePtrStorage<T1, T2, b>& y) {
using std::swap;
swap(x.first(), y.first());
swap(x.second(), y.second());
}
} // up_detail
template <class T>
struct default_delete {
default_delete() {}
template <class U>
default_delete(const default_delete<U>&,
typename butil::enable_if<up_detail::is_convertible<U*, T*>::value>::type* = 0) {}
void operator()(T* ptr) const {
BAIDU_CASSERT(sizeof(T) > 0, T_is_empty);
delete ptr;
}
};
template <class T>
struct default_delete<T[]> {
void operator()(T* ptr) const {
BAIDU_CASSERT(sizeof(T) > 0, T_is_empty);
delete [] ptr;
}
private:
template <class U> void operator()(U*) const;
};
namespace up_detail {
namespace pointer_type_imp {
template <class U> static two test(...);
template <class U> static one test(typename U::pointer* = 0);
} // pointer_type_imp
template <class T>
struct has_pointer_type {
static const bool value = sizeof(pointer_type_imp::test<T>(0)) == 1;
};
namespace pointer_type_imp {
template <class T, class D, bool = has_pointer_type<D>::value>
struct pointer_type {
typedef typename D::pointer type;
};
template <class T, class D>
struct pointer_type<T, D, false> {
typedef T* type;
};
} // pointer_type_imp
template <class T, class D>
struct pointer_type {
typedef typename pointer_type_imp::pointer_type<T,
typename butil::remove_reference<D>::type>::type type;
};
} // up_detail
template <class T, class D = default_delete<T> >
class unique_ptr {
public:
typedef T element_type;
typedef D deleter_type;
typedef typename up_detail::pointer_type<element_type, deleter_type>::type pointer;
private:
up_detail::UniquePtrStorage<pointer, deleter_type> ptr_;
typedef typename butil::add_reference<deleter_type>::type deleter_reference;
typedef typename butil::add_reference<const deleter_type>::type deleter_const_reference;
struct nat {int for_bool_;};
unique_ptr(unique_ptr&);
unique_ptr& operator=(unique_ptr&);
public:
operator up_detail::rv<unique_ptr>() {
return up_detail::rv<unique_ptr>(*this);
}
unique_ptr(up_detail::rv<unique_ptr> r)
: ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {}
unique_ptr& operator=(up_detail::rv<unique_ptr> r) {
reset(r->release());
ptr_.second() = move(r->get_deleter());
return *this;
}
unique_ptr() {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p, typename butil::conditional<butil::is_reference<D>::value,
volatile typename butil::remove_reference<D>::type&, D>::type d)
: ptr_(move(p), forward<D>(const_cast<typename butil::add_reference<D>::type>(d))) {}
template <class U, class E>
unique_ptr(unique_ptr<U, E> u,
typename butil::enable_if <
!butil::is_array<U>::value &&
up_detail::is_convertible<typename unique_ptr<U>::pointer, pointer>::value
&&
up_detail::is_convertible<E, deleter_type>::value &&
(
!butil::is_reference<deleter_type>::value ||
butil::is_same<deleter_type, E>::value)
>::type* = 0)
: ptr_(u.release(), forward<D>(forward<E>(u.get_deleter()))) {}
~unique_ptr() {
BAIDU_CASSERT(!butil::is_reference<deleter_type>::value, deleter_is_ref);
BAIDU_CASSERT(!butil::is_pointer<deleter_type>::value, deleter_is_pointer);
reset();
}
unique_ptr& operator=(int nat::*) {
reset();
return *this;
}
template <class U, class E>
unique_ptr& operator=(unique_ptr<U, E> u) {
reset(u.release());
ptr_.second() = move(u.get_deleter());
return *this;
}
typename butil::add_reference<T>::type operator*() const {return *get();}
pointer operator->() const {return get();}
pointer get() const {return ptr_.first();}
deleter_reference get_deleter() {return ptr_.second();}
deleter_const_reference get_deleter() const {return ptr_.second();}
operator int nat::*() const {return get() ? &nat::for_bool_ : 0;}
void reset(pointer p = pointer()) {
pointer t = get();
if (t != pointer())
get_deleter()(t);
ptr_.first() = p;
}
pointer release() {
pointer tmp = get();
ptr_.first() = pointer();
return tmp;
}
void swap(unique_ptr& u) {up_detail::swap(ptr_, u.ptr_);}
};
template <class T, class D>
class unique_ptr<T[], D> {
public:
typedef T element_type;
typedef D deleter_type;
typedef typename up_detail::pointer_type<element_type, deleter_type>::type pointer;
private:
up_detail::UniquePtrStorage<pointer, deleter_type> ptr_;
typedef typename butil::add_reference<deleter_type>::type deleter_reference;
typedef typename butil::add_reference<const deleter_type>::type deleter_const_reference;
struct nat {int for_bool_;};
unique_ptr(unique_ptr&);
unique_ptr& operator=(unique_ptr&);
public:
operator up_detail::rv<unique_ptr>() {return up_detail::rv<unique_ptr>(*this);}
unique_ptr(up_detail::rv<unique_ptr> r)
: ptr_(r->release(), forward<deleter_type>(r->get_deleter())) {}
unique_ptr& operator=(up_detail::rv<unique_ptr> r) {
reset(r->release());
ptr_.second() = move(r->get_deleter());
return *this;
}
unique_ptr() {}
explicit unique_ptr(pointer p) : ptr_(p) {}
unique_ptr(pointer p, typename butil::conditional<butil::is_reference<D>::value,
volatile typename butil::remove_reference<D>::type&, D>::type d)
: ptr_(move(p), forward<D>(const_cast<typename butil::add_reference<D>::type>(d))) {}
~unique_ptr() {
BAIDU_CASSERT(!butil::is_reference<deleter_type>::value, deleter_is_ref);
BAIDU_CASSERT(!butil::is_pointer<deleter_type>::value, deleter_is_pointer);
reset();
}
T& operator[](size_t i) const {return get()[i];}
pointer get() const {return ptr_.first();}
deleter_reference get_deleter() {return ptr_.second();}
deleter_const_reference get_deleter() const {return ptr_.second();}
operator int nat::*() const {return get() ? &nat::for_bool_ : 0;}
void reset(pointer p = pointer()) {
pointer t = get();
if (t != pointer())
get_deleter()(t);
ptr_.first() = p;
}
pointer release() {
pointer tmp = get();
ptr_.first() = pointer();
return tmp;
}
void swap(unique_ptr& u) {up_detail::swap(ptr_, u.ptr_);}
private:
template <class U>
explicit unique_ptr(
U, typename butil::enable_if<up_detail::is_convertible<U, pointer>::value>::type* = 0);
template <class U>
unique_ptr(U, typename butil::conditional<butil::is_reference<D>::value,
volatile typename butil::remove_reference<D>::type&, D>::type,
typename butil::enable_if<up_detail::is_convertible<U, pointer>::value>::type* = 0);
};
template<class T, class D>
inline
void
swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) {
x.swap(y);
}
template<class T1, class D1, class T2, class D2>
inline
bool
operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) {
return x.get() == y.get();
}
template<class T1, class D1, class T2, class D2>
inline
bool
operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) {
return !(x == y);
}
template<class T1, class D1, class T2, class D2>
inline
bool
operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) {
return x.get() < y.get();
}
template<class T1, class D1, class T2, class D2>
inline
bool
operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) {
return !(y < x);
}
template<class T1, class D1, class T2, class D2>
inline
bool
operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) {
return y < x;
}
template<class T1, class D1, class T2, class D2>
inline
bool
operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y) {
return !(x < y);
}
} // namespace std
#endif // BUTIL_CXX11_ENABLED
#endif // BUTIL_UNIQUE_PTR_H