Mercurial > hg > CbC > CbC_gcc
comparison gcc/testsuite/g++.dg/torture/pr89303.C @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
131:84e7813d76e9 | 145:1830386684a0 |
---|---|
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 } |