xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/bits/shared_ptr.h (revision 946379e7b37692fc43f68eb0d1c10daa0a7f3b6c)
1 // shared_ptr and weak_ptr implementation -*- C++ -*-
2 
3 // Copyright (C) 2007-2013 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library.  This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 // GCC Note: Based on files from version 1.32.0 of the Boost library.
26 
27 //  shared_count.hpp
28 //  Copyright (c) 2001, 2002, 2003 Peter Dimov and Multi Media Ltd.
29 
30 //  shared_ptr.hpp
31 //  Copyright (C) 1998, 1999 Greg Colvin and Beman Dawes.
32 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
33 
34 //  weak_ptr.hpp
35 //  Copyright (C) 2001, 2002, 2003 Peter Dimov
36 
37 //  enable_shared_from_this.hpp
38 //  Copyright (C) 2002 Peter Dimov
39 
40 // Distributed under the Boost Software License, Version 1.0. (See
41 // accompanying file LICENSE_1_0.txt or copy at
42 // http://www.boost.org/LICENSE_1_0.txt)
43 
44 /** @file bits/shared_ptr.h
45  *  This is an internal header file, included by other library headers.
46  *  Do not attempt to use it directly. @headername{memory}
47  */
48 
49 #ifndef _SHARED_PTR_H
50 #define _SHARED_PTR_H 1
51 
52 #include <bits/shared_ptr_base.h>
53 
54 namespace std _GLIBCXX_VISIBILITY(default)
55 {
56 _GLIBCXX_BEGIN_NAMESPACE_VERSION
57 
58   /**
59    * @addtogroup pointer_abstractions
60    * @{
61    */
62 
63   /// 2.2.3.7 shared_ptr I/O
64   template<typename _Ch, typename _Tr, typename _Tp, _Lock_policy _Lp>
65     inline std::basic_ostream<_Ch, _Tr>&
66     operator<<(std::basic_ostream<_Ch, _Tr>& __os,
67 	       const __shared_ptr<_Tp, _Lp>& __p)
68     {
69       __os << __p.get();
70       return __os;
71     }
72 
73   /// 2.2.3.10 shared_ptr get_deleter (experimental)
74   template<typename _Del, typename _Tp, _Lock_policy _Lp>
75     inline _Del*
76     get_deleter(const __shared_ptr<_Tp, _Lp>& __p) noexcept
77     {
78 #ifdef __GXX_RTTI
79       return static_cast<_Del*>(__p._M_get_deleter(typeid(_Del)));
80 #else
81       return 0;
82 #endif
83     }
84 
85 
86   /**
87    *  @brief  A smart pointer with reference-counted copy semantics.
88    *
89    *  The object pointed to is deleted when the last shared_ptr pointing to
90    *  it is destroyed or reset.
91   */
92   template<typename _Tp>
93     class shared_ptr : public __shared_ptr<_Tp>
94     {
95     public:
96       /**
97        *  @brief  Construct an empty %shared_ptr.
98        *  @post   use_count()==0 && get()==0
99        */
100       constexpr shared_ptr() noexcept
101       : __shared_ptr<_Tp>() { }
102 
103       shared_ptr(const shared_ptr&) noexcept = default;
104 
105       /**
106        *  @brief  Construct a %shared_ptr that owns the pointer @a __p.
107        *  @param  __p  A pointer that is convertible to element_type*.
108        *  @post   use_count() == 1 && get() == __p
109        *  @throw  std::bad_alloc, in which case @c delete @a __p is called.
110        */
111       template<typename _Tp1>
112 	explicit shared_ptr(_Tp1* __p)
113         : __shared_ptr<_Tp>(__p) { }
114 
115       /**
116        *  @brief  Construct a %shared_ptr that owns the pointer @a __p
117        *          and the deleter @a __d.
118        *  @param  __p  A pointer.
119        *  @param  __d  A deleter.
120        *  @post   use_count() == 1 && get() == __p
121        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
122        *
123        *  Requirements: _Deleter's copy constructor and destructor must
124        *  not throw
125        *
126        *  __shared_ptr will release __p by calling __d(__p)
127        */
128       template<typename _Tp1, typename _Deleter>
129 	shared_ptr(_Tp1* __p, _Deleter __d)
130         : __shared_ptr<_Tp>(__p, __d) { }
131 
132       /**
133        *  @brief  Construct a %shared_ptr that owns a null pointer
134        *          and the deleter @a __d.
135        *  @param  __p  A null pointer constant.
136        *  @param  __d  A deleter.
137        *  @post   use_count() == 1 && get() == __p
138        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
139        *
140        *  Requirements: _Deleter's copy constructor and destructor must
141        *  not throw
142        *
143        *  The last owner will call __d(__p)
144        */
145       template<typename _Deleter>
146 	shared_ptr(nullptr_t __p, _Deleter __d)
147         : __shared_ptr<_Tp>(__p, __d) { }
148 
149       /**
150        *  @brief  Construct a %shared_ptr that owns the pointer @a __p
151        *          and the deleter @a __d.
152        *  @param  __p  A pointer.
153        *  @param  __d  A deleter.
154        *  @param  __a  An allocator.
155        *  @post   use_count() == 1 && get() == __p
156        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
157        *
158        *  Requirements: _Deleter's copy constructor and destructor must
159        *  not throw _Alloc's copy constructor and destructor must not
160        *  throw.
161        *
162        *  __shared_ptr will release __p by calling __d(__p)
163        */
164       template<typename _Tp1, typename _Deleter, typename _Alloc>
165 	shared_ptr(_Tp1* __p, _Deleter __d, _Alloc __a)
166 	: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
167 
168       /**
169        *  @brief  Construct a %shared_ptr that owns a null pointer
170        *          and the deleter @a __d.
171        *  @param  __p  A null pointer constant.
172        *  @param  __d  A deleter.
173        *  @param  __a  An allocator.
174        *  @post   use_count() == 1 && get() == __p
175        *  @throw  std::bad_alloc, in which case @a __d(__p) is called.
176        *
177        *  Requirements: _Deleter's copy constructor and destructor must
178        *  not throw _Alloc's copy constructor and destructor must not
179        *  throw.
180        *
181        *  The last owner will call __d(__p)
182        */
183       template<typename _Deleter, typename _Alloc>
184 	shared_ptr(nullptr_t __p, _Deleter __d, _Alloc __a)
185 	: __shared_ptr<_Tp>(__p, __d, std::move(__a)) { }
186 
187       // Aliasing constructor
188 
189       /**
190        *  @brief  Constructs a %shared_ptr instance that stores @a __p
191        *          and shares ownership with @a __r.
192        *  @param  __r  A %shared_ptr.
193        *  @param  __p  A pointer that will remain valid while @a *__r is valid.
194        *  @post   get() == __p && use_count() == __r.use_count()
195        *
196        *  This can be used to construct a @c shared_ptr to a sub-object
197        *  of an object managed by an existing @c shared_ptr.
198        *
199        * @code
200        * shared_ptr< pair<int,int> > pii(new pair<int,int>());
201        * shared_ptr<int> pi(pii, &pii->first);
202        * assert(pii.use_count() == 2);
203        * @endcode
204        */
205       template<typename _Tp1>
206 	shared_ptr(const shared_ptr<_Tp1>& __r, _Tp* __p) noexcept
207 	: __shared_ptr<_Tp>(__r, __p) { }
208 
209       /**
210        *  @brief  If @a __r is empty, constructs an empty %shared_ptr;
211        *          otherwise construct a %shared_ptr that shares ownership
212        *          with @a __r.
213        *  @param  __r  A %shared_ptr.
214        *  @post   get() == __r.get() && use_count() == __r.use_count()
215        */
216       template<typename _Tp1, typename = typename
217 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
218 	shared_ptr(const shared_ptr<_Tp1>& __r) noexcept
219         : __shared_ptr<_Tp>(__r) { }
220 
221       /**
222        *  @brief  Move-constructs a %shared_ptr instance from @a __r.
223        *  @param  __r  A %shared_ptr rvalue.
224        *  @post   *this contains the old value of @a __r, @a __r is empty.
225        */
226       shared_ptr(shared_ptr&& __r) noexcept
227       : __shared_ptr<_Tp>(std::move(__r)) { }
228 
229       /**
230        *  @brief  Move-constructs a %shared_ptr instance from @a __r.
231        *  @param  __r  A %shared_ptr rvalue.
232        *  @post   *this contains the old value of @a __r, @a __r is empty.
233        */
234       template<typename _Tp1, typename = typename
235 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
236 	shared_ptr(shared_ptr<_Tp1>&& __r) noexcept
237 	: __shared_ptr<_Tp>(std::move(__r)) { }
238 
239       /**
240        *  @brief  Constructs a %shared_ptr that shares ownership with @a __r
241        *          and stores a copy of the pointer stored in @a __r.
242        *  @param  __r  A weak_ptr.
243        *  @post   use_count() == __r.use_count()
244        *  @throw  bad_weak_ptr when __r.expired(),
245        *          in which case the constructor has no effect.
246        */
247       template<typename _Tp1>
248 	explicit shared_ptr(const weak_ptr<_Tp1>& __r)
249 	: __shared_ptr<_Tp>(__r) { }
250 
251 #if _GLIBCXX_USE_DEPRECATED
252       template<typename _Tp1>
253 	shared_ptr(std::auto_ptr<_Tp1>&& __r);
254 #endif
255 
256       template<typename _Tp1, typename _Del>
257 	shared_ptr(std::unique_ptr<_Tp1, _Del>&& __r)
258 	: __shared_ptr<_Tp>(std::move(__r)) { }
259 
260       /**
261        *  @brief  Construct an empty %shared_ptr.
262        *  @param  __p  A null pointer constant.
263        *  @post   use_count() == 0 && get() == nullptr
264        */
265       constexpr shared_ptr(nullptr_t __p) noexcept
266       : __shared_ptr<_Tp>(__p) { }
267 
268       shared_ptr& operator=(const shared_ptr&) noexcept = default;
269 
270       template<typename _Tp1>
271 	shared_ptr&
272 	operator=(const shared_ptr<_Tp1>& __r) noexcept
273 	{
274 	  this->__shared_ptr<_Tp>::operator=(__r);
275 	  return *this;
276 	}
277 
278 #if _GLIBCXX_USE_DEPRECATED
279       template<typename _Tp1>
280 	shared_ptr&
281 	operator=(std::auto_ptr<_Tp1>&& __r)
282 	{
283 	  this->__shared_ptr<_Tp>::operator=(std::move(__r));
284 	  return *this;
285 	}
286 #endif
287 
288       shared_ptr&
289       operator=(shared_ptr&& __r) noexcept
290       {
291 	this->__shared_ptr<_Tp>::operator=(std::move(__r));
292 	return *this;
293       }
294 
295       template<class _Tp1>
296 	shared_ptr&
297 	operator=(shared_ptr<_Tp1>&& __r) noexcept
298 	{
299 	  this->__shared_ptr<_Tp>::operator=(std::move(__r));
300 	  return *this;
301 	}
302 
303       template<typename _Tp1, typename _Del>
304 	shared_ptr&
305 	operator=(std::unique_ptr<_Tp1, _Del>&& __r)
306 	{
307 	  this->__shared_ptr<_Tp>::operator=(std::move(__r));
308 	  return *this;
309 	}
310 
311     private:
312       // This constructor is non-standard, it is used by allocate_shared.
313       template<typename _Alloc, typename... _Args>
314 	shared_ptr(_Sp_make_shared_tag __tag, const _Alloc& __a,
315 		   _Args&&... __args)
316 	: __shared_ptr<_Tp>(__tag, __a, std::forward<_Args>(__args)...)
317 	{ }
318 
319       template<typename _Tp1, typename _Alloc, typename... _Args>
320 	friend shared_ptr<_Tp1>
321 	allocate_shared(const _Alloc& __a, _Args&&... __args);
322     };
323 
324   // 20.7.2.2.7 shared_ptr comparisons
325   template<typename _Tp1, typename _Tp2>
326     inline bool
327     operator==(const shared_ptr<_Tp1>& __a,
328 	       const shared_ptr<_Tp2>& __b) noexcept
329     { return __a.get() == __b.get(); }
330 
331   template<typename _Tp>
332     inline bool
333     operator==(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
334     { return !__a; }
335 
336   template<typename _Tp>
337     inline bool
338     operator==(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
339     { return !__a; }
340 
341   template<typename _Tp1, typename _Tp2>
342     inline bool
343     operator!=(const shared_ptr<_Tp1>& __a,
344 	       const shared_ptr<_Tp2>& __b) noexcept
345     { return __a.get() != __b.get(); }
346 
347   template<typename _Tp>
348     inline bool
349     operator!=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
350     { return (bool)__a; }
351 
352   template<typename _Tp>
353     inline bool
354     operator!=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
355     { return (bool)__a; }
356 
357   template<typename _Tp1, typename _Tp2>
358     inline bool
359     operator<(const shared_ptr<_Tp1>& __a,
360 	      const shared_ptr<_Tp2>& __b) noexcept
361     {
362       typedef typename std::common_type<_Tp1*, _Tp2*>::type _CT;
363       return std::less<_CT>()(__a.get(), __b.get());
364     }
365 
366   template<typename _Tp>
367     inline bool
368     operator<(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
369     { return std::less<_Tp*>()(__a.get(), nullptr); }
370 
371   template<typename _Tp>
372     inline bool
373     operator<(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
374     { return std::less<_Tp*>()(nullptr, __a.get()); }
375 
376   template<typename _Tp1, typename _Tp2>
377     inline bool
378     operator<=(const shared_ptr<_Tp1>& __a,
379 	       const shared_ptr<_Tp2>& __b) noexcept
380     { return !(__b < __a); }
381 
382   template<typename _Tp>
383     inline bool
384     operator<=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
385     { return !(nullptr < __a); }
386 
387   template<typename _Tp>
388     inline bool
389     operator<=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
390     { return !(__a < nullptr); }
391 
392   template<typename _Tp1, typename _Tp2>
393     inline bool
394     operator>(const shared_ptr<_Tp1>& __a,
395 	      const shared_ptr<_Tp2>& __b) noexcept
396     { return (__b < __a); }
397 
398   template<typename _Tp>
399     inline bool
400     operator>(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
401     { return std::less<_Tp*>()(nullptr, __a.get()); }
402 
403   template<typename _Tp>
404     inline bool
405     operator>(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
406     { return std::less<_Tp*>()(__a.get(), nullptr); }
407 
408   template<typename _Tp1, typename _Tp2>
409     inline bool
410     operator>=(const shared_ptr<_Tp1>& __a,
411 	       const shared_ptr<_Tp2>& __b) noexcept
412     { return !(__a < __b); }
413 
414   template<typename _Tp>
415     inline bool
416     operator>=(const shared_ptr<_Tp>& __a, nullptr_t) noexcept
417     { return !(__a < nullptr); }
418 
419   template<typename _Tp>
420     inline bool
421     operator>=(nullptr_t, const shared_ptr<_Tp>& __a) noexcept
422     { return !(nullptr < __a); }
423 
424   template<typename _Tp>
425     struct less<shared_ptr<_Tp>> : public _Sp_less<shared_ptr<_Tp>>
426     { };
427 
428   // 20.7.2.2.8 shared_ptr specialized algorithms.
429   template<typename _Tp>
430     inline void
431     swap(shared_ptr<_Tp>& __a, shared_ptr<_Tp>& __b) noexcept
432     { __a.swap(__b); }
433 
434   // 20.7.2.2.9 shared_ptr casts.
435   template<typename _Tp, typename _Tp1>
436     inline shared_ptr<_Tp>
437     static_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
438     { return shared_ptr<_Tp>(__r, static_cast<_Tp*>(__r.get())); }
439 
440   template<typename _Tp, typename _Tp1>
441     inline shared_ptr<_Tp>
442     const_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
443     { return shared_ptr<_Tp>(__r, const_cast<_Tp*>(__r.get())); }
444 
445   template<typename _Tp, typename _Tp1>
446     inline shared_ptr<_Tp>
447     dynamic_pointer_cast(const shared_ptr<_Tp1>& __r) noexcept
448     {
449       if (_Tp* __p = dynamic_cast<_Tp*>(__r.get()))
450 	return shared_ptr<_Tp>(__r, __p);
451       return shared_ptr<_Tp>();
452     }
453 
454 
455   /**
456    *  @brief  A smart pointer with weak semantics.
457    *
458    *  With forwarding constructors and assignment operators.
459    */
460   template<typename _Tp>
461     class weak_ptr : public __weak_ptr<_Tp>
462     {
463     public:
464       constexpr weak_ptr() noexcept
465       : __weak_ptr<_Tp>() { }
466 
467       template<typename _Tp1, typename = typename
468 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
469 	weak_ptr(const weak_ptr<_Tp1>& __r) noexcept
470 	: __weak_ptr<_Tp>(__r) { }
471 
472       template<typename _Tp1, typename = typename
473 	       std::enable_if<std::is_convertible<_Tp1*, _Tp*>::value>::type>
474 	weak_ptr(const shared_ptr<_Tp1>& __r) noexcept
475 	: __weak_ptr<_Tp>(__r) { }
476 
477       template<typename _Tp1>
478 	weak_ptr&
479 	operator=(const weak_ptr<_Tp1>& __r) noexcept
480 	{
481 	  this->__weak_ptr<_Tp>::operator=(__r);
482 	  return *this;
483 	}
484 
485       template<typename _Tp1>
486 	weak_ptr&
487 	operator=(const shared_ptr<_Tp1>& __r) noexcept
488 	{
489 	  this->__weak_ptr<_Tp>::operator=(__r);
490 	  return *this;
491 	}
492 
493       shared_ptr<_Tp>
494       lock() const noexcept
495       {
496 #ifdef __GTHREADS
497 	if (this->expired())
498 	  return shared_ptr<_Tp>();
499 
500 	__try
501 	  {
502 	    return shared_ptr<_Tp>(*this);
503 	  }
504 	__catch(const bad_weak_ptr&)
505 	  {
506 	    return shared_ptr<_Tp>();
507 	  }
508 #else
509 	return this->expired() ? shared_ptr<_Tp>() : shared_ptr<_Tp>(*this);
510 #endif
511       }
512     };
513 
514   // 20.7.2.3.6 weak_ptr specialized algorithms.
515   template<typename _Tp>
516     inline void
517     swap(weak_ptr<_Tp>& __a, weak_ptr<_Tp>& __b) noexcept
518     { __a.swap(__b); }
519 
520 
521   /// Primary template owner_less
522   template<typename _Tp>
523     struct owner_less;
524 
525   /// Partial specialization of owner_less for shared_ptr.
526   template<typename _Tp>
527     struct owner_less<shared_ptr<_Tp>>
528     : public _Sp_owner_less<shared_ptr<_Tp>, weak_ptr<_Tp>>
529     { };
530 
531   /// Partial specialization of owner_less for weak_ptr.
532   template<typename _Tp>
533     struct owner_less<weak_ptr<_Tp>>
534     : public _Sp_owner_less<weak_ptr<_Tp>, shared_ptr<_Tp>>
535     { };
536 
537   /**
538    *  @brief Base class allowing use of member function shared_from_this.
539    */
540   template<typename _Tp>
541     class enable_shared_from_this
542     {
543     protected:
544       constexpr enable_shared_from_this() noexcept { }
545 
546       enable_shared_from_this(const enable_shared_from_this&) noexcept { }
547 
548       enable_shared_from_this&
549       operator=(const enable_shared_from_this&) noexcept
550       { return *this; }
551 
552       ~enable_shared_from_this() { }
553 
554     public:
555       shared_ptr<_Tp>
556       shared_from_this()
557       { return shared_ptr<_Tp>(this->_M_weak_this); }
558 
559       shared_ptr<const _Tp>
560       shared_from_this() const
561       { return shared_ptr<const _Tp>(this->_M_weak_this); }
562 
563     private:
564       template<typename _Tp1>
565 	void
566 	_M_weak_assign(_Tp1* __p, const __shared_count<>& __n) const noexcept
567 	{ _M_weak_this._M_assign(__p, __n); }
568 
569       template<typename _Tp1>
570 	friend void
571 	__enable_shared_from_this_helper(const __shared_count<>& __pn,
572 					 const enable_shared_from_this* __pe,
573 					 const _Tp1* __px) noexcept
574 	{
575 	  if (__pe != 0)
576 	    __pe->_M_weak_assign(const_cast<_Tp1*>(__px), __pn);
577 	}
578 
579       mutable weak_ptr<_Tp>  _M_weak_this;
580     };
581 
582   /**
583    *  @brief  Create an object that is owned by a shared_ptr.
584    *  @param  __a     An allocator.
585    *  @param  __args  Arguments for the @a _Tp object's constructor.
586    *  @return A shared_ptr that owns the newly created object.
587    *  @throw  An exception thrown from @a _Alloc::allocate or from the
588    *          constructor of @a _Tp.
589    *
590    *  A copy of @a __a will be used to allocate memory for the shared_ptr
591    *  and the new object.
592    */
593   template<typename _Tp, typename _Alloc, typename... _Args>
594     inline shared_ptr<_Tp>
595     allocate_shared(const _Alloc& __a, _Args&&... __args)
596     {
597       return shared_ptr<_Tp>(_Sp_make_shared_tag(), __a,
598 			     std::forward<_Args>(__args)...);
599     }
600 
601   /**
602    *  @brief  Create an object that is owned by a shared_ptr.
603    *  @param  __args  Arguments for the @a _Tp object's constructor.
604    *  @return A shared_ptr that owns the newly created object.
605    *  @throw  std::bad_alloc, or an exception thrown from the
606    *          constructor of @a _Tp.
607    */
608   template<typename _Tp, typename... _Args>
609     inline shared_ptr<_Tp>
610     make_shared(_Args&&... __args)
611     {
612       typedef typename std::remove_const<_Tp>::type _Tp_nc;
613       return std::allocate_shared<_Tp>(std::allocator<_Tp_nc>(),
614 				       std::forward<_Args>(__args)...);
615     }
616 
617   /// std::hash specialization for shared_ptr.
618   template<typename _Tp>
619     struct hash<shared_ptr<_Tp>>
620     : public __hash_base<size_t, shared_ptr<_Tp>>
621     {
622       size_t
623       operator()(const shared_ptr<_Tp>& __s) const noexcept
624       { return std::hash<_Tp*>()(__s.get()); }
625     };
626 
627   // @} group pointer_abstractions
628 
629 _GLIBCXX_END_NAMESPACE_VERSION
630 } // namespace
631 
632 #endif // _SHARED_PTR_H
633