145
|
1 // PR middle-end/89303
|
|
2 // { dg-do run }
|
|
3 // { dg-additional-options "-std=c++14" }
|
|
4
|
|
5 namespace my
|
|
6 {
|
|
7 typedef __SIZE_TYPE__ size_t;
|
|
8 typedef decltype(nullptr) nullptr_t;
|
|
9
|
|
10 template<typename _Tp, _Tp __v>
|
|
11 struct integral_constant
|
|
12 {
|
|
13 static constexpr _Tp value = __v;
|
|
14 typedef _Tp value_type;
|
|
15 typedef integral_constant<_Tp, __v> type;
|
|
16 constexpr operator value_type() const noexcept { return value; }
|
|
17 constexpr value_type operator()() const noexcept { return value; }
|
|
18 };
|
|
19
|
|
20 template<typename _Tp, _Tp __v>
|
|
21 constexpr _Tp integral_constant<_Tp, __v>::value;
|
|
22
|
|
23 typedef integral_constant<bool, true> true_type;
|
|
24 typedef integral_constant<bool, false> false_type;
|
|
25
|
|
26 template<bool __v>
|
|
27 using __bool_constant = integral_constant<bool, __v>;
|
|
28
|
|
29 template<bool, typename, typename>
|
|
30 struct conditional;
|
|
31
|
|
32 template<typename...>
|
|
33 struct __and_;
|
|
34
|
|
35 template<>
|
|
36 struct __and_<>
|
|
37 : public true_type
|
|
38 { };
|
|
39
|
|
40 template<typename _B1>
|
|
41 struct __and_<_B1>
|
|
42 : public _B1
|
|
43 { };
|
|
44
|
|
45 template<typename _B1, typename _B2>
|
|
46 struct __and_<_B1, _B2>
|
|
47 : public conditional<_B1::value, _B2, _B1>::type
|
|
48 { };
|
|
49
|
|
50 template<typename _B1, typename _B2, typename _B3, typename... _Bn>
|
|
51 struct __and_<_B1, _B2, _B3, _Bn...>
|
|
52 : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type
|
|
53 { };
|
|
54
|
|
55 template<typename>
|
|
56 struct remove_cv;
|
|
57
|
|
58 template<typename>
|
|
59 struct __is_void_helper
|
|
60 : public false_type { };
|
|
61
|
|
62 template<>
|
|
63 struct __is_void_helper<void>
|
|
64 : public true_type { };
|
|
65
|
|
66 template<typename _Tp>
|
|
67 struct is_void
|
|
68 : public __is_void_helper<typename remove_cv<_Tp>::type>::type
|
|
69 { };
|
|
70
|
|
71 template<typename _Tp, typename _Up = _Tp&&>
|
|
72 _Up
|
|
73 __declval(int);
|
|
74
|
|
75 template<typename _Tp>
|
|
76 _Tp
|
|
77 __declval(long);
|
|
78
|
|
79 template<typename _Tp>
|
|
80 auto declval() noexcept -> decltype(__declval<_Tp>(0));
|
|
81
|
|
82 template<typename, typename>
|
|
83 struct is_same
|
|
84 : public false_type { };
|
|
85
|
|
86 template<typename _Tp>
|
|
87 struct is_same<_Tp, _Tp>
|
|
88 : public true_type { };
|
|
89
|
|
90 template<typename _Tp>
|
|
91 struct remove_const
|
|
92 { typedef _Tp type; };
|
|
93
|
|
94 template<typename _Tp>
|
|
95 struct remove_const<_Tp const>
|
|
96 { typedef _Tp type; };
|
|
97
|
|
98 template<typename _Tp>
|
|
99 struct remove_volatile
|
|
100 { typedef _Tp type; };
|
|
101
|
|
102 template<typename _Tp>
|
|
103 struct remove_volatile<_Tp volatile>
|
|
104 { typedef _Tp type; };
|
|
105
|
|
106 template<typename _Tp>
|
|
107 struct remove_cv
|
|
108 {
|
|
109 typedef typename
|
|
110 remove_const<typename remove_volatile<_Tp>::type>::type type;
|
|
111 };
|
|
112
|
|
113 template<typename _Tp>
|
|
114 struct remove_reference
|
|
115 { typedef _Tp type; };
|
|
116
|
|
117 template<typename _Tp>
|
|
118 struct remove_reference<_Tp&>
|
|
119 { typedef _Tp type; };
|
|
120
|
|
121 template<typename _Tp>
|
|
122 struct remove_reference<_Tp&&>
|
|
123 { typedef _Tp type; };
|
|
124
|
|
125 template<bool, typename _Tp = void>
|
|
126 struct enable_if
|
|
127 { };
|
|
128
|
|
129 template<typename _Tp>
|
|
130 struct enable_if<true, _Tp>
|
|
131 { typedef _Tp type; };
|
|
132
|
|
133 template<typename... _Cond>
|
|
134 using _Require = typename enable_if<__and_<_Cond...>::value>::type;
|
|
135
|
|
136 template<bool _Cond, typename _Iftrue, typename _Iffalse>
|
|
137 struct conditional
|
|
138 { typedef _Iftrue type; };
|
|
139
|
|
140 template<typename _Iftrue, typename _Iffalse>
|
|
141 struct conditional<false, _Iftrue, _Iffalse>
|
|
142 { typedef _Iffalse type; };
|
|
143
|
|
144 template<typename _Tp>
|
|
145 struct __declval_protector
|
|
146 {
|
|
147 static const bool __stop = false;
|
|
148 };
|
|
149
|
|
150 template<typename _Tp>
|
|
151 auto declval() noexcept -> decltype(__declval<_Tp>(0))
|
|
152 {
|
|
153 static_assert(__declval_protector<_Tp>::__stop,
|
|
154 "declval() must not be used!");
|
|
155 return __declval<_Tp>(0);
|
|
156 }
|
|
157
|
|
158 namespace void_details {
|
|
159 template <class... >
|
|
160 struct make_void { using type = void; };
|
|
161 }
|
|
162
|
|
163 template <class... T> using __void_t = typename void_details ::make_void<T...>::type;
|
|
164
|
|
165 template<typename _Tp>
|
|
166 inline constexpr _Tp*
|
|
167 __addressof(_Tp& __r) noexcept
|
|
168 {
|
|
169 return reinterpret_cast<_Tp*>
|
|
170 (&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
|
|
171 }
|
|
172
|
|
173 template<typename _Tp>
|
|
174 constexpr _Tp&&
|
|
175 forward(typename my::remove_reference<_Tp>::type& __t) noexcept
|
|
176 { return static_cast<_Tp&&>(__t); }
|
|
177
|
|
178 template<typename _Tp>
|
|
179 constexpr _Tp&&
|
|
180 forward(typename my::remove_reference<_Tp>::type&& __t) noexcept
|
|
181 {
|
|
182 return static_cast<_Tp&&>(__t);
|
|
183 }
|
|
184
|
|
185 template<typename _Tp>
|
|
186 constexpr typename my::remove_reference<_Tp>::type&&
|
|
187 move(_Tp&& __t) noexcept
|
|
188 { return static_cast<typename my::remove_reference<_Tp>::type&&>(__t); }
|
|
189 }
|
|
190
|
|
191 inline void* operator new(my::size_t, void* p) { return p; }
|
|
192
|
|
193 extern "C" void* malloc(my::size_t);
|
|
194 extern "C" void free(void*);
|
|
195
|
|
196 namespace my
|
|
197 {
|
|
198 template<typename T>
|
|
199 class allocator
|
|
200 {
|
|
201 public:
|
|
202 using value_type = T;
|
|
203
|
|
204 allocator() { }
|
|
205
|
|
206 template<typename U>
|
|
207 allocator(const allocator<U>&) { }
|
|
208
|
|
209 T* allocate(size_t n) { return (T*)malloc(n*sizeof(T)); }
|
|
210 void deallocate(T* p, size_t) { free(p); }
|
|
211
|
|
212 template<typename U, typename... Args>
|
|
213 void construct(U* p, Args&&... args)
|
|
214 { ::new((void*)p) U(args...); }
|
|
215
|
|
216 template<typename U>
|
|
217 void destroy(U* p)
|
|
218 { p->~U(); }
|
|
219 };
|
|
220
|
|
221 class __undefined;
|
|
222
|
|
223 template<typename _Tp, typename _Up>
|
|
224 struct __replace_first_arg
|
|
225 { };
|
|
226
|
|
227 template<template<typename, typename...> class _Template, typename _Up,
|
|
228 typename _Tp, typename... _Types>
|
|
229 struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
|
|
230 { using type = _Template<_Up, _Types...>; };
|
|
231
|
|
232 struct __allocator_traits_base
|
|
233 {
|
|
234 template<typename _Tp, typename _Up, typename = void>
|
|
235 struct __rebind : __replace_first_arg<_Tp, _Up> { };
|
|
236
|
|
237 template<typename _Tp, typename _Up>
|
|
238 struct __rebind<_Tp, _Up,
|
|
239 __void_t<typename _Tp::template rebind<_Up>::other>>
|
|
240 { using type = typename _Tp::template rebind<_Up>::other; };
|
|
241 };
|
|
242
|
|
243 template<typename _Alloc, typename _Up>
|
|
244 using __alloc_rebind
|
|
245 = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type;
|
|
246
|
|
247 template<typename _Alloc>
|
|
248 struct allocator_traits;
|
|
249
|
|
250 template<typename _Tp>
|
|
251 struct allocator_traits<allocator<_Tp>>
|
|
252 {
|
|
253 using allocator_type = allocator<_Tp>;
|
|
254 using value_type = _Tp;
|
|
255 using pointer = _Tp*;
|
|
256 using const_pointer = const _Tp*;
|
|
257 using size_type = my::size_t;
|
|
258
|
|
259 static pointer
|
|
260 allocate(allocator_type& __a, size_type __n)
|
|
261 { return __a.allocate(__n); }
|
|
262
|
|
263 static void
|
|
264 deallocate(allocator_type& __a, pointer __p, size_type __n)
|
|
265 { __a.deallocate(__p, __n); }
|
|
266
|
|
267 template<typename _Up, typename... _Args>
|
|
268 static void
|
|
269 construct(allocator_type& __a, _Up* __p, _Args&&... __args)
|
|
270 { __a.construct(__p, my::forward<_Args>(__args)...); }
|
|
271
|
|
272 template<typename _Up>
|
|
273 static void
|
|
274 destroy(allocator_type& __a, _Up* __p)
|
|
275 { __a.destroy(__p); }
|
|
276 };
|
|
277
|
|
278 template<typename _Alloc>
|
|
279 struct __allocated_ptr
|
|
280 {
|
|
281 using pointer = typename allocator_traits<_Alloc>::pointer;
|
|
282 using value_type = typename allocator_traits<_Alloc>::value_type;
|
|
283
|
|
284 __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept
|
|
285 : _M_alloc(my::__addressof(__a)), _M_ptr(__ptr)
|
|
286 { }
|
|
287
|
|
288 template<typename _Ptr,
|
|
289 typename _Req = _Require<is_same<_Ptr, value_type*>>>
|
|
290 __allocated_ptr(_Alloc& __a, _Ptr __ptr)
|
|
291 : _M_alloc(my::__addressof(__a)),
|
|
292 _M_ptr(__ptr)
|
|
293 { }
|
|
294
|
|
295 __allocated_ptr(__allocated_ptr&& __gd) noexcept
|
|
296 : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr)
|
|
297 { __gd._M_ptr = nullptr; }
|
|
298
|
|
299 ~__allocated_ptr()
|
|
300 {
|
|
301 if (_M_ptr != nullptr)
|
|
302 my::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1);
|
|
303 }
|
|
304
|
|
305 __allocated_ptr&
|
|
306 operator=(my::nullptr_t) noexcept
|
|
307 {
|
|
308 _M_ptr = nullptr;
|
|
309 return *this;
|
|
310 }
|
|
311
|
|
312 value_type* get() { return _M_ptr; }
|
|
313
|
|
314 private:
|
|
315 _Alloc* _M_alloc;
|
|
316 pointer _M_ptr;
|
|
317 };
|
|
318
|
|
319 template<typename _Alloc>
|
|
320 __allocated_ptr<_Alloc>
|
|
321 __allocate_guarded(_Alloc& __a)
|
|
322 {
|
|
323 return { __a, my::allocator_traits<_Alloc>::allocate(__a, 1) };
|
|
324 }
|
|
325
|
|
326 template<typename _Tp>
|
|
327 struct __aligned_buffer
|
|
328 {
|
|
329 alignas(__alignof__(_Tp)) unsigned char _M_storage[sizeof(_Tp)];
|
|
330 __aligned_buffer() = default;
|
|
331
|
|
332 void*
|
|
333 _M_addr() noexcept
|
|
334 {
|
|
335 return static_cast<void*>(&_M_storage);
|
|
336 }
|
|
337
|
|
338 const void*
|
|
339 _M_addr() const noexcept
|
|
340 {
|
|
341 return static_cast<const void*>(&_M_storage);
|
|
342 }
|
|
343
|
|
344 _Tp*
|
|
345 _M_ptr() noexcept
|
|
346 { return static_cast<_Tp*>(_M_addr()); }
|
|
347
|
|
348 const _Tp*
|
|
349 _M_ptr() const noexcept
|
|
350 { return static_cast<const _Tp*>(_M_addr()); }
|
|
351 };
|
|
352
|
|
353 class bad_weak_ptr { };
|
|
354
|
|
355 inline void
|
|
356 __throw_bad_weak_ptr()
|
|
357 { (throw (bad_weak_ptr())); }
|
|
358
|
|
359 class _Sp_counted_base
|
|
360 {
|
|
361 public:
|
|
362 _Sp_counted_base() noexcept
|
|
363 : _M_use_count(1), _M_weak_count(1) { }
|
|
364
|
|
365 virtual
|
|
366 ~_Sp_counted_base() noexcept
|
|
367 { }
|
|
368
|
|
369 virtual void
|
|
370 _M_dispose() noexcept = 0;
|
|
371
|
|
372 virtual void
|
|
373 _M_destroy() noexcept
|
|
374 { delete this; }
|
|
375
|
|
376 void
|
|
377 _M_add_ref_copy()
|
|
378 { ++_M_use_count; }
|
|
379
|
|
380 void
|
|
381 _M_add_ref_lock()
|
|
382 {
|
|
383 if (_M_use_count == 0)
|
|
384 __throw_bad_weak_ptr();
|
|
385 ++_M_use_count;
|
|
386 }
|
|
387
|
|
388 void
|
|
389 _M_release() noexcept
|
|
390 {
|
|
391 if (--_M_use_count == 0)
|
|
392 {
|
|
393 _M_dispose();
|
|
394 if (--_M_weak_count == 0)
|
|
395 _M_destroy();
|
|
396 }
|
|
397 }
|
|
398
|
|
399 void
|
|
400 _M_weak_add_ref() noexcept
|
|
401 { ++_M_weak_count; }
|
|
402
|
|
403 void
|
|
404 _M_weak_release() noexcept
|
|
405 {
|
|
406 if (--_M_weak_count == 0)
|
|
407 _M_destroy();
|
|
408 }
|
|
409
|
|
410 long
|
|
411 _M_get_use_count() const noexcept
|
|
412 {
|
|
413 return _M_use_count;
|
|
414 }
|
|
415
|
|
416 private:
|
|
417 _Sp_counted_base(_Sp_counted_base const&) = delete;
|
|
418 _Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
|
|
419
|
|
420 int _M_use_count;
|
|
421 int _M_weak_count;
|
|
422 };
|
|
423
|
|
424 template<typename _Tp>
|
|
425 class shared_ptr;
|
|
426
|
|
427 template<typename _Tp>
|
|
428 class weak_ptr;
|
|
429
|
|
430 template<typename _Tp>
|
|
431 class enable_shared_from_this;
|
|
432
|
|
433 class __weak_count;
|
|
434
|
|
435 class __shared_count;
|
|
436
|
|
437 template<typename _Alloc>
|
|
438 struct _Sp_alloc_shared_tag
|
|
439 {
|
|
440 const _Alloc& _M_a;
|
|
441 };
|
|
442
|
|
443 template<typename _Tp, typename _Alloc>
|
|
444 class _Sp_counted_ptr_inplace final : public _Sp_counted_base
|
|
445 {
|
|
446 class _Impl : _Alloc
|
|
447 {
|
|
448 public:
|
|
449 explicit _Impl(_Alloc __a) noexcept : _Alloc(__a) { }
|
|
450
|
|
451 _Alloc& _M_alloc() noexcept { return *this; }
|
|
452
|
|
453 __aligned_buffer<_Tp> _M_storage;
|
|
454 };
|
|
455
|
|
456 public:
|
|
457 using __allocator_type = __alloc_rebind<_Alloc, _Sp_counted_ptr_inplace>;
|
|
458
|
|
459 template<typename... _Args>
|
|
460 _Sp_counted_ptr_inplace(_Alloc __a, _Args&&... __args)
|
|
461 : _M_impl(__a)
|
|
462 {
|
|
463 allocator_traits<_Alloc>::construct(__a, _M_ptr(),
|
|
464 my::forward<_Args>(__args)...);
|
|
465 }
|
|
466
|
|
467 ~_Sp_counted_ptr_inplace() noexcept { }
|
|
468
|
|
469 virtual void
|
|
470 _M_dispose() noexcept
|
|
471 {
|
|
472 allocator_traits<_Alloc>::destroy(_M_impl._M_alloc(), _M_ptr());
|
|
473 }
|
|
474
|
|
475 virtual void
|
|
476 _M_destroy() noexcept
|
|
477 {
|
|
478 __allocator_type __a(_M_impl._M_alloc());
|
|
479 __allocated_ptr<__allocator_type> __guard_ptr{ __a, this };
|
|
480 this->~_Sp_counted_ptr_inplace();
|
|
481 }
|
|
482
|
|
483 private:
|
|
484 friend class __shared_count;
|
|
485
|
|
486 _Tp* _M_ptr() noexcept { return _M_impl._M_storage._M_ptr(); }
|
|
487
|
|
488 _Impl _M_impl;
|
|
489 };
|
|
490
|
|
491 class __shared_count
|
|
492 {
|
|
493 public:
|
|
494 constexpr __shared_count() noexcept : _M_pi(0)
|
|
495 { }
|
|
496
|
|
497 template<typename _Tp, typename _Alloc, typename... _Args>
|
|
498 __shared_count(_Tp*& __p, _Sp_alloc_shared_tag<_Alloc> __a,
|
|
499 _Args&&... __args)
|
|
500 {
|
|
501 typedef _Sp_counted_ptr_inplace<_Tp, _Alloc> _Sp_cp_type;
|
|
502 typename _Sp_cp_type::__allocator_type __a2(__a._M_a);
|
|
503 auto __guard = my::__allocate_guarded(__a2);
|
|
504 _Sp_cp_type* __mem = __guard.get();
|
|
505 auto __pi = ::new (__mem)
|
|
506 _Sp_cp_type(__a._M_a, my::forward<_Args>(__args)...);
|
|
507 __guard = nullptr;
|
|
508 _M_pi = __pi;
|
|
509 __p = __pi->_M_ptr();
|
|
510 }
|
|
511
|
|
512 ~__shared_count() noexcept
|
|
513 {
|
|
514 if (_M_pi != nullptr)
|
|
515 _M_pi->_M_release();
|
|
516 }
|
|
517
|
|
518 __shared_count(const __shared_count& __r) noexcept
|
|
519 : _M_pi(__r._M_pi)
|
|
520 {
|
|
521 if (_M_pi != 0)
|
|
522 _M_pi->_M_add_ref_copy();
|
|
523 }
|
|
524
|
|
525 explicit __shared_count(const __weak_count& __r);
|
|
526
|
|
527 long
|
|
528 _M_get_use_count() const noexcept
|
|
529 { return _M_pi != 0 ? _M_pi->_M_get_use_count() : 0; }
|
|
530
|
|
531 private:
|
|
532 friend class __weak_count;
|
|
533
|
|
534 _Sp_counted_base* _M_pi;
|
|
535 };
|
|
536
|
|
537 class __weak_count
|
|
538 {
|
|
539 public:
|
|
540 constexpr __weak_count() noexcept : _M_pi(nullptr)
|
|
541 { }
|
|
542
|
|
543 __weak_count(const __shared_count& __r) noexcept
|
|
544 : _M_pi(__r._M_pi)
|
|
545 {
|
|
546 if (_M_pi != nullptr)
|
|
547 _M_pi->_M_weak_add_ref();
|
|
548 }
|
|
549
|
|
550 __weak_count(const __weak_count& __r) noexcept
|
|
551 : _M_pi(__r._M_pi)
|
|
552 {
|
|
553 if (_M_pi != nullptr)
|
|
554 _M_pi->_M_weak_add_ref();
|
|
555 }
|
|
556
|
|
557 __weak_count(__weak_count&& __r) noexcept
|
|
558 : _M_pi(__r._M_pi)
|
|
559 { __r._M_pi = nullptr; }
|
|
560
|
|
561 ~__weak_count() noexcept
|
|
562 {
|
|
563 if (_M_pi != nullptr)
|
|
564 {
|
|
565 _M_pi->_M_weak_release();
|
|
566 }
|
|
567 }
|
|
568
|
|
569 __weak_count&
|
|
570 operator=(const __shared_count& __r) noexcept
|
|
571 {
|
|
572 _Sp_counted_base* __tmp = __r._M_pi;
|
|
573 if (__tmp != nullptr)
|
|
574 __tmp->_M_weak_add_ref();
|
|
575 if (_M_pi != nullptr)
|
|
576 _M_pi->_M_weak_release();
|
|
577 _M_pi = __tmp;
|
|
578 return *this;
|
|
579 }
|
|
580
|
|
581 long
|
|
582 _M_get_use_count() const noexcept
|
|
583 { return _M_pi != nullptr ? _M_pi->_M_get_use_count() : 0; }
|
|
584
|
|
585 private:
|
|
586 friend class __shared_count;
|
|
587
|
|
588 _Sp_counted_base* _M_pi;
|
|
589 };
|
|
590
|
|
591 inline
|
|
592 __shared_count::__shared_count(const __weak_count& __r)
|
|
593 : _M_pi(__r._M_pi)
|
|
594 {
|
|
595 if (_M_pi != nullptr)
|
|
596 _M_pi->_M_add_ref_lock();
|
|
597 else
|
|
598 __throw_bad_weak_ptr();
|
|
599 }
|
|
600
|
|
601 template<typename _Tp>
|
|
602 class shared_ptr
|
|
603 {
|
|
604 public:
|
|
605 using element_type = _Tp;
|
|
606
|
|
607 constexpr shared_ptr() noexcept
|
|
608 : _M_ptr(0), _M_refcount()
|
|
609 { }
|
|
610
|
|
611 shared_ptr(const shared_ptr&) noexcept = default;
|
|
612 shared_ptr& operator=(const shared_ptr&) noexcept = default;
|
|
613 ~shared_ptr() = default;
|
|
614
|
|
615 template<typename _Yp>
|
|
616 explicit shared_ptr(const weak_ptr<_Yp>& __r)
|
|
617 : _M_refcount(__r._M_refcount) // may throw
|
|
618 {
|
|
619 // It is now safe to copy __r._M_ptr, as
|
|
620 // _M_refcount(__r._M_refcount) did not throw.
|
|
621 _M_ptr = __r._M_ptr;
|
|
622 }
|
|
623
|
|
624 long
|
|
625 use_count() const noexcept
|
|
626 { return _M_refcount._M_get_use_count(); }
|
|
627
|
|
628 element_type* operator->() const noexcept { return _M_ptr; }
|
|
629
|
|
630 protected:
|
|
631
|
|
632 template<typename _Alloc, typename... _Args>
|
|
633 shared_ptr(_Sp_alloc_shared_tag<_Alloc> __tag, _Args&&... __args)
|
|
634 : _M_ptr(), _M_refcount(_M_ptr, __tag, my::forward<_Args>(__args)...)
|
|
635 { _M_enable_shared_from_this_with(_M_ptr); }
|
|
636
|
|
637 template<typename _Tp1, typename _Alloc,
|
|
638 typename... _Args>
|
|
639 friend shared_ptr<_Tp1>
|
|
640 allocate_shared(const _Alloc& __a, _Args&&... __args);
|
|
641
|
|
642 friend class weak_ptr<_Tp>;
|
|
643
|
|
644 private:
|
|
645
|
|
646 template<typename _Yp>
|
|
647 using __esft_base_t = decltype(__enable_shared_from_this_base(
|
|
648 my::declval<const __shared_count&>(),
|
|
649 my::declval<_Yp*>()));
|
|
650
|
|
651 template<typename _Yp, typename = void>
|
|
652 struct __has_esft_base
|
|
653 : false_type { };
|
|
654
|
|
655 template<typename _Yp>
|
|
656 struct __has_esft_base<_Yp, __void_t<__esft_base_t<_Yp>>>
|
|
657 : true_type { };
|
|
658
|
|
659 template<typename _Yp, typename _Yp2 = typename remove_cv<_Yp>::type>
|
|
660 typename enable_if<__has_esft_base<_Yp2>::value>::type
|
|
661 _M_enable_shared_from_this_with(_Yp* __p) noexcept
|
|
662 {
|
|
663 if (auto __base = __enable_shared_from_this_base(_M_refcount, __p))
|
|
664 __base->_M_weak_assign(const_cast<_Yp2*>(__p), _M_refcount);
|
|
665 }
|
|
666
|
|
667 template<typename _Tp1> friend class shared_ptr;
|
|
668 template<typename _Tp1> friend class weak_ptr;
|
|
669
|
|
670 element_type* _M_ptr;
|
|
671 __shared_count _M_refcount;
|
|
672 };
|
|
673
|
|
674 template<typename _Tp>
|
|
675 class weak_ptr
|
|
676 {
|
|
677 public:
|
|
678 using element_type = _Tp;
|
|
679
|
|
680 constexpr weak_ptr() noexcept
|
|
681 : _M_ptr(nullptr), _M_refcount()
|
|
682 { }
|
|
683
|
|
684 weak_ptr(const weak_ptr&) noexcept = default;
|
|
685
|
|
686 ~weak_ptr() = default;
|
|
687
|
|
688 weak_ptr&
|
|
689 operator=(const weak_ptr& __r) noexcept = default;
|
|
690
|
|
691 long
|
|
692 use_count() const noexcept
|
|
693 { return _M_refcount._M_get_use_count(); }
|
|
694
|
|
695 private:
|
|
696
|
|
697 void
|
|
698 _M_assign(_Tp* __ptr, const __shared_count& __refcount) noexcept
|
|
699 {
|
|
700 if (use_count() == 0)
|
|
701 {
|
|
702 _M_ptr = __ptr;
|
|
703 _M_refcount = __refcount;
|
|
704 }
|
|
705 }
|
|
706
|
|
707 template<typename _Tp1> friend class shared_ptr;
|
|
708 template<typename _Tp1> friend class weak_ptr;
|
|
709 friend class enable_shared_from_this<_Tp>;
|
|
710
|
|
711 element_type* _M_ptr;
|
|
712 __weak_count _M_refcount;
|
|
713 };
|
|
714
|
|
715 template<typename _Tp>
|
|
716 class enable_shared_from_this
|
|
717 {
|
|
718 protected:
|
|
719 constexpr enable_shared_from_this() noexcept { }
|
|
720
|
|
721 enable_shared_from_this(const enable_shared_from_this&) noexcept { }
|
|
722
|
|
723 enable_shared_from_this&
|
|
724 operator=(const enable_shared_from_this&) noexcept
|
|
725 { return *this; }
|
|
726
|
|
727 ~enable_shared_from_this() { }
|
|
728
|
|
729 public:
|
|
730 shared_ptr<_Tp>
|
|
731 shared_from_this()
|
|
732 { return shared_ptr<_Tp>(this->_M_weak_this); }
|
|
733
|
|
734 shared_ptr<const _Tp>
|
|
735 shared_from_this() const
|
|
736 { return shared_ptr<const _Tp>(this->_M_weak_this); }
|
|
737
|
|
738 private:
|
|
739 template<typename _Tp1>
|
|
740 void
|
|
741 _M_weak_assign(_Tp1* __p, const __shared_count& __n) const noexcept
|
|
742 { _M_weak_this._M_assign(__p, __n); }
|
|
743
|
|
744 friend const enable_shared_from_this*
|
|
745 __enable_shared_from_this_base(const __shared_count&,
|
|
746 const enable_shared_from_this* __p)
|
|
747 { return __p; }
|
|
748
|
|
749 template<typename>
|
|
750 friend class shared_ptr;
|
|
751
|
|
752 mutable weak_ptr<_Tp> _M_weak_this;
|
|
753 };
|
|
754
|
|
755 template<typename _Tp, typename _Alloc, typename... _Args>
|
|
756 inline shared_ptr<_Tp>
|
|
757 allocate_shared(const _Alloc& __a, _Args&&... __args)
|
|
758 {
|
|
759 return shared_ptr<_Tp>(_Sp_alloc_shared_tag<_Alloc>{__a},
|
|
760 my::forward<_Args>(__args)...);
|
|
761 }
|
|
762
|
|
763 template<typename _Tp, typename... _Args>
|
|
764 inline shared_ptr<_Tp>
|
|
765 make_shared(_Args&&... __args)
|
|
766 {
|
|
767 typedef typename my::remove_const<_Tp>::type _Tp_nc;
|
|
768 return my::allocate_shared<_Tp>(my::allocator<_Tp_nc>(),
|
|
769 my::forward<_Args>(__args)...);
|
|
770 }
|
|
771 }
|
|
772
|
|
773 class blob final: public my::enable_shared_from_this<blob>
|
|
774 {
|
|
775 int* data;
|
|
776
|
|
777 public:
|
|
778 blob() { data = new int; }
|
|
779 ~blob() { delete data; }
|
|
780 };
|
|
781
|
|
782 static int
|
|
783 bar(my::shared_ptr<blob>)
|
|
784 {
|
|
785 return 0;
|
|
786 }
|
|
787
|
|
788 int main()
|
|
789 {
|
|
790 my::shared_ptr<blob> tg = my::make_shared<blob>();
|
|
791 return tg->shared_from_this().use_count() - 2;
|
|
792 }
|