throwing_ptr
Smart pointers that throw on dereference if null
shared_ptr.hpp
Go to the documentation of this file.
1 // Copyright Claudio Bantaloukas 2017-2018.
2 // Distributed under the Boost Software License, Version 1.0.
3 // (See accompanying file LICENSE or copy at
4 // http://www.boost.org/LICENSE_1_0.txt)
5 /** \file shared_ptr.hpp throwing/shared_ptr.hpp
6  * \brief throwing::shared_ptr implementation
7  */
8 
9 #pragma once
10 #include <atomic>
11 #include <functional>
12 #include <iosfwd>
13 #include <memory>
14 #include <throwing/null_ptr_exception.hpp>
15 #include <throwing/private/compiler_checks.hpp>
16 
17 /** \namespace throwing
18  * \brief Implementations of throwing::shared_ptr, throwing::unique_ptr and
19  * related
20  */
21 namespace throwing {
22 
23 /*! \class throwing::shared_ptr throwing/shared_ptr.hpp
24  * \brief Wrapper aroung std::shared_ptr that throws when a wrapped null
25  * pointer is dereferenced
26  *
27  * throwing::shared_ptr is a smart pointer that retains shared ownership of an
28  * object through a pointer. Several shared_ptr objects may own the same object.
29  * The object is destroyed and its memory deallocated when either of the
30  * following happens:
31  * - the last remaining shared_ptr owning the object is destroyed;
32  * - the last remaining shared_ptr owning the object is assigned another pointer
33  * via operator= or reset().
34  *
35  * The object is destroyed using delete-expression or a custom deleter that is
36  * supplied to shared_ptr during construction.
37  *
38  * A shared_ptr can share ownership of an object while storing a pointer to
39  * another object. This feature can be used to point to member objects while
40  * owning the object they belong to. The stored pointer is the one accessed by
41  * get(), the dereference and the comparison operators. The managed pointer is
42  * the one passed to the deleter when use count reaches zero.
43  *
44  * A shared_ptr may also own no objects, in which case it is called empty (an
45  * empty shared_ptr may have a non-null stored pointer if the aliasing
46  * constructor was used to create it).
47  *
48  * All specializations of shared_ptr meet the requirements of CopyConstructible,
49  * CopyAssignable, and LessThanComparable and are contextually convertible to
50  * bool.
51  *
52  * All member functions (including copy constructor and copy assignment) can be
53  * called by multiple threads on different instances of shared_ptr without
54  * additional synchronization even if these instances are copies and share
55  * ownership of the same object. If multiple threads of execution access the
56  * same shared_ptr without synchronization and any of those accesses uses a
57  * non-const member function of shared_ptr then a data race will occur; the
58  * shared_ptr overloads of atomic functions can be used to prevent the data
59  * race.
60  *
61  * The underlying std::shared_ptr is available via get_std_shared_ptr()
62  */
63 template <typename T> class shared_ptr {
64 public:
65  /** \brief the type pointed to. */
66  typedef typename std::shared_ptr<T>::element_type element_type;
67 
68  // allow access to p for other throwing::shared_ptr instantiations
69  template <typename Y> friend class shared_ptr;
70 
71  /** \brief Constructs a shared_ptr with no managed object, i.e. empty
72  * shared_ptr.
73  */
75 
76  /** \brief Constructs a shared_ptr with no managed object, i.e. empty
77  * shared_ptr.
78  */
79  TSP_CONSTEXPR shared_ptr(std::nullptr_t ptr) TSP_NOEXCEPT : p(ptr) {}
80 
81  /** \brief Constructs a shared_ptr with ptr as the pointer to the managed
82  * object.
83  */
84  template <class Y> explicit shared_ptr(Y *ptr) : p(ptr) {}
85 
86  /** \brief Constructs a shared_ptr with ptr as the pointer to the managed
87  * object.
88  *
89  * Uses the specified deleter d as the deleter.
90  *
91  * The expression d(ptr) must be well formed, have well-defined behavior and
92  * not throw any exceptions.
93  *
94  * The construction of d and of the stored deleter from d must not throw
95  * exceptions.
96  */
97  template <class Y, class Deleter>
98  shared_ptr(Y *ptr, Deleter d) : p(ptr, d) {}
99 
100  /** \brief Constructs a shared_ptr with ptr as the pointer to the managed
101  * object.
102  *
103  * Uses the specified deleter d as the deleter.
104  *
105  * The expression d(ptr) must be well formed, have well-defined behavior and
106  * not throw any exceptions.
107  *
108  * The construction of d and of the stored deleter from d must not throw
109  * exceptions.
110  */
111  template <class Deleter>
112  shared_ptr(std::nullptr_t ptr, Deleter d) : p(ptr, d) {}
113 
114  /** \brief Constructs a shared_ptr with ptr as the pointer to the managed
115  * object.
116  *
117  * Uses the specified deleter d as the deleter.
118  *
119  * The expression d(ptr) must be well formed, have well-defined behavior and
120  * not throw any exceptions.
121  *
122  * The construction of d and of the stored deleter from d must
123  * not throw exceptions.
124  *
125  * Uses a copy of alloc for allocation of data for internal use.
126  *
127  * Alloc must be a Allocator.
128  */
129  template <class Y, class Deleter, class Alloc>
130  shared_ptr(Y *ptr, Deleter d, Alloc alloc) : p(ptr, d, alloc) {}
131 
132  /** \brief The aliasing constructor
133  *
134  * Constructs a shared_ptr which shares ownership information with r, but
135  * holds an unrelated and unmanaged pointer ptr. Even if this shared_ptr is
136  * the last of the group to go out of scope, it will call the destructor for
137  * the object originally managed by r.
138  *
139  * However, calling get() on this will always return a copy of ptr.
140  *
141  * It is the responsibility of the programmer to make sure that this ptr
142  * remains valid as long as this shared_ptr exists, such as in the typical
143  * use cases where ptr is a member of the object managed by r or is an alias
144  * (e.g., downcast) of r.get()
145  */
146  template <class Y>
148  : p(r.p, ptr) {}
149 
150  /** \brief Constructs a shared_ptr which shares ownership of the object
151  * managed by r.
152  *
153  * If r manages no object, *this manages no object too.
154  */
156 
157  /** \brief Constructs a shared_ptr which shares ownership of the object
158  * managed by r.
159  *
160  * If r manages no object, *this manages no object too.
161  */
162  template <class Y>
163  shared_ptr(const shared_ptr<Y> &r) TSP_NOEXCEPT : p(r.p) {}
164 
165  /** \brief Move-constructs a shared_ptr from r.
166  *
167  * After the construction, *this contains a copy of the previous state of r,
168  * r is empty and its stored pointer is null.
169  */
171 
172  /** \brief Move-constructs a shared_ptr from r.
173  *
174  * After the construction, *this contains a copy of the previous state of r,
175  * r is empty and its stored pointer is null.
176  */
177  template <class Y>
179 
180  /** \brief Constructs a shared_ptr which shares ownership of the object
181  * managed by r.
182  *
183  * If r manages no object, *this manages no object too.
184  */
185  shared_ptr(const std::shared_ptr<T> &r) TSP_NOEXCEPT : p(r) {}
186 
187  /** \brief Constructs a shared_ptr which shares ownership of the object
188  * managed by r.
189  *
190  * If r manages no object, *this manages no object too.
191  */
192  template <class Y>
193  shared_ptr(const std::shared_ptr<Y> &r) TSP_NOEXCEPT : p(r) {}
194 
195  /** \brief Move-constructs a shared_ptr from r.
196  *
197  * After the construction, *this contains a copy of the previous state of r,
198  * r is empty and its stored pointer is null.
199  */
200  shared_ptr(std::shared_ptr<T> &&r) TSP_NOEXCEPT : p(std::move(r)) {}
201 
202  /** \brief Move-constructs a shared_ptr from r.
203  *
204  * After the construction, *this contains a copy of the previous state of r,
205  * r is empty and its stored pointer is null.
206  */
207  template <class Y>
208  shared_ptr(std::shared_ptr<Y> &&r) TSP_NOEXCEPT : p(std::move(r)) {}
209 
210  /** \brief Constructs a shared_ptr which shares ownership of the object
211  * managed by r.
212  *
213  * Y* must be implicitly convertible to T*. (until C++17)
214  *
215  * This overload only participates in overload resolution if Y* is
216  * compatible with T*. (since C++17)
217  *
218  * Note that r.lock() may be used for the same purpose: the difference is
219  * that this constructor throws an exception if the argument is empty, while
220  * std::weak_ptr<T>::lock() constructs an empty std::shared_ptr in that
221  * case.
222  */
223  template <class Y> explicit shared_ptr(const std::weak_ptr<Y> &r) : p(r) {}
224 
225  /**\brief Constructs a shared_ptr which manages the object currently managed
226  * by r.
227  *
228  * The deleter associated with r is stored for future deletion of the
229  * managed object.
230  *
231  * r manages no object after the call.
232  *
233  * This overload doesn't participate in overload resolution if
234  * std::unique_ptr<Y, Deleter>::pointer is not compatible with T*.
235  * If r.get() is a null pointer, this overload is equivalent to the default
236  * constructor (1). (since C++17)
237  *
238  * If Deleter is a reference type, equivalent to shared_ptr(r.release(),
239  * std::ref(r.get_deleter()).
240  * Otherwise, equivalent to shared_ptr(r.release(), r.get_deleter())
241  */
242  template <class Y, class Deleter>
243  shared_ptr(std::unique_ptr<Y, Deleter> &&r) : p(std::move(r)) {}
244 
245  /** \brief Destructor
246  * If *this owns an object and it is the last shared_ptr owning it, the
247  * object is destroyed through the owned deleter.
248  * After the destruction, the smart pointers that shared ownership with
249  * *this, if any, will report a use_count() that is one less than its
250  * previous value.
251 
252  * Notes:
253 
254  * Unlike throwing::unique_ptr, the throwing of std::shared_ptr is invoked
255  * even if the managed pointer is null.
256  */
257  ~shared_ptr() = default;
258 
259  /** \brief Assignment operator
260  *
261  * Replaces the managed object with the one managed by r.
262  * If *this already owns an object and it is the last shared_ptr owning it,
263  * and r is not the same as *this, the object is destroyed through the owned
264  * deleter.
265  *
266  * Shares ownership of the object managed by r. If r manages no object,
267  * *this manages no object too.
268  * Equivalent to shared_ptr<T>(r).swap(*this).
269  */
271  p = r.p;
272  return *this;
273  }
274 
275  /** \brief Assignment operator
276  *
277  * Replaces the managed object with the one managed by r.
278  * If *this already owns an object and it is the last shared_ptr owning it,
279  * and r is not the same as *this, the object is destroyed through the owned
280  * deleter.
281  *
282  * Shares ownership of the object managed by r. If r manages no object,
283  * *this manages no object too.
284  * Equivalent to shared_ptr<T>(r).swap(*this).
285  */
286  template <class Y>
288  p = r.p;
289  return *this;
290  }
291 
292  /** \brief Assignment operator
293  *
294  * Replaces the managed object with the one managed by r.
295  * If *this already owns an object and it is the last shared_ptr owning it,
296  * and r is not the same as *this, the object is destroyed through the owned
297  * deleter.
298  *
299  * Move-assigns a shared_ptr from r. After the assignment, *this contains a
300  * copy of the previous state of r, r is empty. Equivalent to
301  * shared_ptr<T>(std::move(r)).swap(*this)
302  */
304  p = std::move(r.p);
305  return *this;
306  }
307 
308  /** \brief Assignment operator
309  *
310  * Replaces the managed object with the one managed by r.
311  * If *this already owns an object and it is the last shared_ptr owning it,
312  * and r is not the same as *this, the object is destroyed through the owned
313  * deleter.
314  *
315  * Move-assigns a shared_ptr from r. After the assignment, *this contains a
316  * copy of the previous state of r, r is empty. Equivalent to
317  * shared_ptr<T>(std::move(r)).swap(*this)
318  */
319  template <class Y> shared_ptr &operator=(shared_ptr<Y> &&r) TSP_NOEXCEPT {
320  p = std::move(r.p);
321  return *this;
322  }
323 
324  /** \brief Assignment operator
325  *
326  * Replaces the managed object with the one managed by r.
327  * If *this already owns an object and it is the last shared_ptr owning it,
328  * and r is not the same as *this, the object is destroyed through the owned
329  * deleter.
330  *
331  * Transfers the ownership of the object managed by r to *this. The deleter
332  * associated to r is stored for future deletion of the managed object. r
333  * manages no object after the call. Equivalent to
334  * shared_ptr<T>(std::move(r)).swap(*this).
335  */
336  template <class Y, class Deleter>
337  shared_ptr &operator=(std::unique_ptr<Y, Deleter> &&r) {
338  p = std::move(r);
339  return *this;
340  }
341 
342  /** \brief Exchanges the contents of *this and r
343  */
345 
346  /** \brief Releases the ownership of the managed object, if any.
347  *
348  * If *this already owns an object and it is the last shared_ptr owning it,
349  * the object is destroyed through the owned deleter.
350  * If the object pointed to by ptr is already owned, the function results in
351  * undefined behavior.
352  *
353  * After the call, *this manages no object.
354  * Equivalent to shared_ptr().swap(*this);
355  */
356  void reset() TSP_NOEXCEPT { p.reset(); }
357 
358  /** \brief Replaces the managed object with an object pointed to by ptr.
359  *
360  * Y must be a complete type and implicitly convertible to T.
361  *
362  * Uses the delete expression as the deleter. A valid delete expression must
363  * be available, i.e. delete ptr must be well formed, have well-defined
364  * behavior and not throw any exceptions.
365  *
366  * Equivalent to shared_ptr<T>(ptr).swap(*this);
367  */
368  template <class Y> void reset(Y *ptr) { p.reset(ptr); }
369 
370  /** \brief Replaces the managed object with an object pointed to by ptr.
371  *
372  * Y must be a complete type and implicitly convertible to T.
373  *
374  * Uses the specified deleter d as the deleter. Deleter must be callable for
375  * the type T, i.e. d(ptr) must be well formed, have well-defined behavior
376  * and not throw any exceptions. Deleter must be CopyConstructible, and its
377  * copy constructor and destructor must not throw exceptions.
378  *
379  * Equivalent to shared_ptr<T>(ptr, d).swap(*this);
380  */
381  template <class Y, class Deleter> void reset(Y *ptr, Deleter d) {
382  p.reset(ptr, d);
383  }
384 
385  /** \brief Replaces the managed object with an object pointed to by ptr.
386  *
387  * Y must be a complete type and implicitly convertible to T.
388  *
389  * Uses the specified deleter d as the deleter. Deleter must be callable for
390  * the type T, i.e. d(ptr) must be well formed, have well-defined behavior
391  * and not throw any exceptions. Deleter must be CopyConstructible, and its
392  * copy constructor and destructor must not throw exceptions.
393  *
394  * Additionally uses a copy of alloc for allocation of data for internal
395  * use. Alloc must be a Allocator. The copy constructor and destructor must
396  * not throw exceptions.
397  *
398  * Equivalent to shared_ptr<T>(ptr, d, alloc).swap(*this);
399  */
400  template <class Y, class Deleter, class Alloc>
401  void reset(Y *ptr, Deleter d, Alloc alloc) {
402  p.reset(ptr, d, alloc);
403  }
404 
405  /** \brief Returns the stored pointer.
406  */
407  element_type *get() const TSP_NOEXCEPT { return p.get(); }
408 
409  /** \brief Returns the underlying std::shared_pointer.
410  */
411  const std::shared_ptr<T> &get_std_shared_ptr() const TSP_NOEXCEPT {
412  return p;
413  }
414 
415  /** \brief Returns the underlying std::shared_pointer.
416  */
417  std::shared_ptr<T> &get_std_shared_ptr() TSP_NOEXCEPT { return p; }
418 
419  /** \brief Dereferences the stored pointer.
420  *
421  * \throw null_ptr_exception<T> if the pointer is null
422  */
423  T &operator*() const {
424  const auto ptr = get();
425  if (nullptr == ptr)
426  throw null_ptr_exception<T>();
427  return *ptr;
428  }
429 
430  /** \brief Dereferences the stored pointer.
431  *
432  * \throw null_ptr_exception<T> if the pointer is null
433  */
434  T *operator->() const {
435  const auto ptr = get();
436  if (nullptr == ptr)
437  throw null_ptr_exception<T>();
438  return ptr;
439  }
440 
442  /** \brief Index into the array pointed to by the stored pointer.
443  *
444  * The behavior is undefined if the stored pointer is null or if idx is
445  * negative.
446  *
447  * If T (the template parameter of shared_ptr) is an array type U[N], idx
448  * must be less than N, otherwise the behavior is undefined.
449  *
450  * This method is available if the underlying compiler and c++ library
451  * implementation support it
452  *
453  * Throws null_ptr_exception<T> if the pointer is null
454  */
456  if (!p)
457  throw null_ptr_exception<T>();
458  return p.operator[](idx);
459  }
460 #endif
461 
462  /** \brief Returns the number of different shared_ptr instances (this
463  * included) managing the current object.
464  *
465  * If there is no managed object, ​0​ is returned.
466  *
467  * In multithreaded environment, the value returned by use_count is
468  * approximate (typical implementations use a memory_order_relaxed load)
469  */
470  long use_count() const TSP_NOEXCEPT { return p.use_count(); }
471 
472  /** \brief Checks if *this stores a non-null pointer, i.e. whether get() !=
473  * nullptr.
474  */
475  explicit operator bool() const TSP_NOEXCEPT { return p.operator bool(); }
476 
477  /** \brief Checks whether this shared_ptr precedes other in implementation
478  * defined owner-based (as opposed to value-based) order.
479  *
480  * The order is such that two smart pointers compare equivalent only if they
481  * are both empty or if they both own the same object, even if the values of
482  * the pointers obtained by get() are different (e.g. because they point at
483  * different subobjects within the same object)
484  *
485  * This ordering is used to make shared and weak pointers usable as keys in
486  * associative containers, typically through std::owner_less.
487  */
488  template <class Y>
489  bool owner_before(const shared_ptr<Y> &other) const TSP_NOEXCEPT {
490  return p.owner_before(other.p);
491  }
492 
493  /** \brief Checks whether this shared_ptr precedes other in implementation
494  * defined owner-based (as opposed to value-based) order.
495  *
496  * The order is such that two smart pointers compare equivalent only if they
497  * are both empty or if they both own the same object, even if the values of
498  * the pointers obtained by get() are different (e.g. because they point at
499  * different subobjects within the same object)
500  *
501  * This ordering is used to make shared and weak pointers usable as keys in
502  * associative containers, typically through std::owner_less.
503  */
504  template <class Y>
505  bool owner_before(const std::shared_ptr<Y> &other) const TSP_NOEXCEPT {
506  return p.owner_before(other);
507  }
508 
509  /** \brief Checks whether this shared_ptr precedes other in implementation
510  * defined owner-based (as opposed to value-based) order.
511  *
512  * The order is such that two smart pointers compare equivalent only if they
513  * are both empty or if they both own the same object, even if the values of
514  * the pointers obtained by get() are different (e.g. because they point at
515  * different subobjects within the same object)
516  *
517  * This ordering is used to make shared and weak pointers usable as keys in
518  * associative containers, typically through std::owner_less.
519  */
520  template <class Y>
521  bool owner_before(const std::weak_ptr<Y> &other) const TSP_NOEXCEPT {
522  return p.owner_before(other);
523  }
524 
525 private:
526  std::shared_ptr<T> p;
527 };
528 
529 /** \brief Specializes the std::swap algorithm for throwing::shared_ptr.
530  *
531  * Swaps the pointers of lhs and rhs.
532  *
533  * Calls lhs.swap(rhs).
534  */
535 template <class T>
536 void swap(throwing::shared_ptr<T> &lhs,
537  throwing::shared_ptr<T> &rhs) TSP_NOEXCEPT {
538  lhs.swap(rhs);
539 }
540 
541 /** \brief Constructs an object of type T and wraps it in a throwing::shared_ptr
542  * using args as the parameter list for the constructor of T.
543  *
544  * The object is constructed as if by the expression ::new (pv)
545  * T(std::forward<Args>(args)...), where pv is an internal void* pointer to
546  * storage suitable to hold an object of type T.
547  *
548  * The storage is typically larger than sizeof(T) in order to use one allocation
549  * for both the control block of the shared pointer and the T object.
550  *
551  * The shared_ptr constructor called by this function enables
552  * shared_from_this with a pointer to the newly constructed object of type T.
553  *
554  * This overload only participates in overload resolution if T is not an array
555  * type
556  */
557 template <class T, class... Args> shared_ptr<T> make_shared(Args &&... args) {
558  return shared_ptr<T>(
559  std::move(std::make_shared<T>(std::forward<Args>(args)...)));
560 }
561 
562 /** \brief Constructs an object of type T and wraps it in a throwing::shared_ptr
563  * using args as the parameter list for the constructor of T.
564  *
565  * The object is constructed as if by the expression
566  * std::allocator_traits<A2>::construct(a, pv, v)), where pv is an internal
567  * void* pointer to storage suitable to hold an object of type T and a is the
568  * possibly-rebound copy of the allocator.
569  *
570  * The storage is typically larger than sizeof(T) in order to use one allocation
571  * for both the control block of the shared pointer and the T object.
572  *
573  * The shared_ptr constructor called by this function enables shared_from_this
574  * with a pointer to the newly constructed object of type T.
575  *
576  * All memory allocation is done using a copy of alloc, which must satisfy the
577  * Allocator requirements.
578  *
579  * This overload only participates in overload resolution if T is not an array
580  * type
581  */
582 template <class T, class Alloc, class... Args>
583 shared_ptr<T> allocate_shared(const Alloc &alloc, Args &&... args) {
584  return shared_ptr<T>(std::move(
586 }
587 
588 /** \brief Creates a new instance of shared_ptr whose stored pointer is obtained
589  * from r's stored pointer using a static_cast expression.
590  *
591  * If r is empty, so is the new shared_ptr (but its stored pointer is not
592  * necessarily null).
593  *
594  * Otherwise, the new shared_ptr will share ownership with r.
595  *
596  * The behavior is undefined unless static_cast<T*>((U*)nullptr) is well formed.
597  */
598 template <class T, class U>
600  auto p = static_cast<typename shared_ptr<T>::element_type *>(r.get());
601  return shared_ptr<T>(r, p);
602 }
603 
604 /** \brief Creates a new instance of shared_ptr whose stored pointer is obtained
605  * from r's stored pointer using a dynamic_cast expression.
606  *
607  * If r is empty, so is the new shared_ptr (but its stored pointer is not
608  * necessarily null).
609  *
610  * Otherwise, the new shared_ptr will share ownership with r, except that it is
611  * empty if the dynamic_cast performed by dynamic_pointer_cast returns a null
612  * pointer.
613  *
614  * The behavior is undefined unless dynamic_cast<T*>((U*)nullptr) is well
615  * formed.
616  */
617 template <class T, class U>
619  if (auto p =
620  dynamic_cast<typename shared_ptr<T>::element_type *>(r.get())) {
621  return shared_ptr<T>(r, p);
622  } else {
623  return shared_ptr<T>();
624  }
625 }
626 
627 /** \brief Creates a new instance of shared_ptr whose stored pointer is obtained
628  * from r's stored pointer using a const_cast expression.
629  *
630  * If r is empty, so is the new shared_ptr (but its stored pointer is not
631  * necessarily null).
632  *
633  * Otherwise, the new shared_ptr will share ownership with r.
634  *
635  * The behavior is undefined unless const_cast<T*>((U*)nullptr) is well formed.
636  */
637 template <class T, class U>
639  auto p = const_cast<typename shared_ptr<T>::element_type *>(r.get());
640  return shared_ptr<T>(r, p);
641 }
642 
643 /** \brief Creates a new instance of shared_ptr whose stored pointer is obtained
644  * from r's stored pointer using a reinterpret_cast expression.
645  *
646  * If r is empty, so is the new shared_ptr (but its stored pointer is not
647  * necessarily null).
648  *
649  * Otherwise, the new shared_ptr will share ownership with r.
650  *
651  * The behavior is undefined unless reinterpret_cast<T*>((U*)nullptr) is well
652  * formed.
653  */
654 template <class T, class U>
656  auto p = reinterpret_cast<typename shared_ptr<T>::element_type *>(r.get());
657  return shared_ptr<T>(r, p);
658 }
659 
660 /** \brief Access to the p's deleter.
661  *
662  * If the shared pointer p owns a deleter of type cv-unqualified Deleter (e.g.
663  * if it was created with one of the constructors that take a deleter as a
664  * parameter), then returns a pointer to the deleter. Otherwise, returns a null
665  * pointer.
666  */
667 template <class Deleter, class T>
668 Deleter *get_deleter(const shared_ptr<T> &p) TSP_NOEXCEPT {
670 }
671 
672 /** \brief Compare two shared_ptr objects
673  * \return lhs.get() == rhs.get()
674  */
675 template <class T, class U>
676 bool operator==(const shared_ptr<T> &lhs,
677  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
679 }
680 
681 /** \brief Compare two shared_ptr objects
682  * \return !(lhs == rhs)
683  */
684 template <class T, class U>
685 bool operator!=(const shared_ptr<T> &lhs,
686  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
688 }
689 
690 /** \brief Compare two shared_ptr objects
691  * \return std::less<V>()(lhs.get(), rhs.get()), where V is the composite
692  * pointer type of std::shared_ptr<T>::element_type* and
693  * std::shared_ptr<U>::element_type*
694  */
695 template <class T, class U>
696 bool operator<(const shared_ptr<T> &lhs,
697  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
699 }
700 
701 /** \brief Compare two shared_ptr objects
702  * \return rhs < lhs
703  */
704 template <class T, class U>
705 bool operator>(const shared_ptr<T> &lhs,
706  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
708 }
709 
710 /** \brief Compare two shared_ptr objects
711  * \return !(rhs < lhs)
712  */
713 template <class T, class U>
714 bool operator<=(const shared_ptr<T> &lhs,
715  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
717 }
718 
719 /** \brief Compare two shared_ptr objects
720  * \return !(lhs < rhs)
721  */
722 template <class T, class U>
723 bool operator>=(const shared_ptr<T> &lhs,
724  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
726 }
727 
728 /** \brief Compare two shared_ptr objects
729  * \return lhs.get() == rhs.get()
730  */
731 template <class T, class U>
732 bool operator==(const std::shared_ptr<T> &lhs,
733  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
734  return lhs == rhs.get_std_shared_ptr();
735 }
736 
737 /** \brief Compare two shared_ptr objects
738  * \return !(lhs == rhs)
739  */
740 template <class T, class U>
741 bool operator!=(const std::shared_ptr<T> &lhs,
742  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
743  return lhs != rhs.get_std_shared_ptr();
744 }
745 
746 /** \brief Compare two shared_ptr objects
747  * \return std::less<V>()(lhs.get(), rhs.get()), where V is the composite
748  * pointer type of std::shared_ptr<T>::element_type* and
749  * std::shared_ptr<U>::element_type*
750  */
751 template <class T, class U>
752 bool operator<(const std::shared_ptr<T> &lhs,
753  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
754  return lhs < rhs.get_std_shared_ptr();
755 }
756 
757 /** \brief Compare two shared_ptr objects
758  * \return rhs < lhs
759  */
760 template <class T, class U>
761 bool operator>(const std::shared_ptr<T> &lhs,
762  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
763  return lhs > rhs.get_std_shared_ptr();
764 }
765 
766 /** \brief Compare two shared_ptr objects
767  * \return !(rhs < lhs)
768  */
769 template <class T, class U>
770 bool operator<=(const std::shared_ptr<T> &lhs,
771  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
772  return lhs <= rhs.get_std_shared_ptr();
773 }
774 
775 /** \brief Compare two shared_ptr objects
776  * \return !(lhs < rhs)
777  */
778 template <class T, class U>
779 bool operator>=(const std::shared_ptr<T> &lhs,
780  const shared_ptr<U> &rhs) TSP_NOEXCEPT {
781  return lhs >= rhs.get_std_shared_ptr();
782 }
783 
784 /** \brief Compare two shared_ptr objects
785  * \return lhs.get() == rhs.get()
786  */
787 template <class T, class U>
788 bool operator==(const shared_ptr<T> &lhs,
789  const std::shared_ptr<U> &rhs) TSP_NOEXCEPT {
790  return lhs.get_std_shared_ptr() == rhs;
791 }
792 
793 /** \brief Compare two shared_ptr objects
794  * \return !(lhs == rhs)
795  */
796 template <class T, class U>
797 bool operator!=(const shared_ptr<T> &lhs,
798  const std::shared_ptr<U> &rhs) TSP_NOEXCEPT {
799  return lhs.get_std_shared_ptr() != rhs;
800 }
801 
802 /** \brief Compare two shared_ptr objects
803  * \return std::less<V>()(lhs.get(), rhs.get()), where V is the composite
804  * pointer type of std::shared_ptr<T>::element_type* and
805  * std::shared_ptr<U>::element_type*
806  */
807 template <class T, class U>
808 bool operator<(const shared_ptr<T> &lhs,
809  const std::shared_ptr<U> &rhs) TSP_NOEXCEPT {
810  return lhs.get_std_shared_ptr() < rhs;
811 }
812 
813 /** \brief Compare two shared_ptr objects
814  * \return rhs < lhs
815  */
816 template <class T, class U>
817 bool operator>(const shared_ptr<T> &lhs,
818  const std::shared_ptr<U> &rhs) TSP_NOEXCEPT {
819  return lhs.get_std_shared_ptr() > rhs;
820 }
821 
822 /** \brief Compare two shared_ptr objects
823  * \return !(rhs < lhs)
824  */
825 template <class T, class U>
826 bool operator<=(const shared_ptr<T> &lhs,
827  const std::shared_ptr<U> &rhs) TSP_NOEXCEPT {
828  return lhs.get_std_shared_ptr() <= rhs;
829 }
830 
831 /** \brief Compare two shared_ptr objects
832  * \return !(lhs < rhs)
833  */
834 template <class T, class U>
835 bool operator>=(const shared_ptr<T> &lhs,
836  const std::shared_ptr<U> &rhs) TSP_NOEXCEPT {
837  return lhs.get_std_shared_ptr() >= rhs;
838 }
839 
840 /** \brief Compare a shared_ptr with a null pointer
841  * \return !lhs
842  */
843 template <class T>
844 bool operator==(const shared_ptr<T> &lhs, std::nullptr_t rhs) TSP_NOEXCEPT {
845  return lhs.get_std_shared_ptr() == rhs;
846 }
847 
848 /** \brief Compare a shared_ptr with a null pointer
849  * \return !rhs
850  */
851 template <class T>
852 bool operator==(std::nullptr_t lhs, const shared_ptr<T> &rhs) TSP_NOEXCEPT {
853  return lhs == rhs.get_std_shared_ptr();
854 }
855 
856 /** \brief Compare a shared_ptr with a null pointer
857  * \return (bool)lhs
858  */
859 template <class T>
860 bool operator!=(const shared_ptr<T> &lhs, std::nullptr_t rhs) TSP_NOEXCEPT {
861  return lhs.get_std_shared_ptr() != rhs;
862 }
863 
864 /** \brief Compare a shared_ptr with a null pointer
865  * \return (bool)rhs
866  */
867 template <class T>
868 bool operator!=(std::nullptr_t lhs, const shared_ptr<T> &rhs) TSP_NOEXCEPT {
869  return lhs != rhs.get_std_shared_ptr();
870 }
871 
872 /** \brief Compare a shared_ptr with a null pointer
873  * \return std::less<shared_ptr<T>::element_type*>()(lhs.get(), nullptr)
874  */
875 template <class T>
876 bool operator<(const shared_ptr<T> &lhs, std::nullptr_t rhs) TSP_NOEXCEPT {
877  return lhs.get_std_shared_ptr() < rhs;
878 }
879 
880 /** \brief Compare a shared_ptr with a null pointer
881  * \return std::less<shared_ptr<T>::element_type*>()(nullptr, rhs.get())
882  */
883 template <class T>
884 bool operator<(std::nullptr_t lhs, const shared_ptr<T> &rhs) TSP_NOEXCEPT {
885  return lhs < rhs.get_std_shared_ptr();
886 }
887 
888 /** \brief Compare a shared_ptr with a null pointer
889  * \return nullptr < lhs
890  */
891 template <class T>
892 bool operator>(const shared_ptr<T> &lhs, std::nullptr_t rhs) TSP_NOEXCEPT {
893  return lhs.get_std_shared_ptr() > rhs;
894 }
895 
896 /** \brief Compare a shared_ptr with a null pointer
897  * \return rhs < nullptr
898  */
899 template <class T>
900 bool operator>(std::nullptr_t lhs, const shared_ptr<T> &rhs) TSP_NOEXCEPT {
901  return lhs > rhs.get_std_shared_ptr();
902 }
903 
904 /** \brief Compare a shared_ptr with a null pointer
905  * \return !(nullptr < lhs)
906  */
907 template <class T>
908 bool operator<=(const shared_ptr<T> &lhs, std::nullptr_t rhs) TSP_NOEXCEPT {
909  return lhs.get_std_shared_ptr() <= rhs;
910 }
911 
912 /** \brief Compare a shared_ptr with a null pointer
913  * \return !(rhs < nullptr)
914  */
915 template <class T>
916 bool operator<=(std::nullptr_t lhs, const shared_ptr<T> &rhs) TSP_NOEXCEPT {
917  return lhs <= rhs.get_std_shared_ptr();
918 }
919 
920 /** \brief Compare a shared_ptr with a null pointer
921  * \return !(lhs < nullptr)
922  */
923 template <class T>
924 bool operator>=(const shared_ptr<T> &lhs, std::nullptr_t rhs) TSP_NOEXCEPT {
925  return lhs.get_std_shared_ptr() >= rhs;
926 }
927 
928 /** \brief Compare a shared_ptr with a null pointer
929  * \return !(nullptr < rhs)
930  */
931 template <class T>
932 bool operator>=(std::nullptr_t lhs, const shared_ptr<T> &rhs) TSP_NOEXCEPT {
933  return lhs >= rhs.get_std_shared_ptr();
934 }
935 
936 /** \brief Inserts the value of the pointer stored in ptr into the output stream
937  * os
938  *
939  * Equivalent to os << ptr.get().
940  * \return os
941  */
942 template <class T, class U, class V>
943 std::basic_ostream<U, V> &operator<<(std::basic_ostream<U, V> &os,
944  const shared_ptr<T> &ptr) {
945  os << ptr.get();
946  return os;
947 }
948 
949 #if !(!defined(__clang__) && defined(__GNUC__) &&
950  __GNUC__ < 5) // These operations are not supported in GCC < 5.0
951 
952 /** \brief Determines whether atomic access to the shared pointer pointed-to by
953  * p is lock-free.
954  */
955 template <class T> bool atomic_is_lock_free(shared_ptr<T> const *p) {
956  return atomic_is_lock_free(reinterpret_cast<std::shared_ptr<T> const *>(p));
957 }
958 
959 /** \brief Equivalent to atomic_load_explicit(p, std::memory_order_seq_cst)
960  */
961 template <class T> shared_ptr<T> atomic_load(const shared_ptr<T> *p) {
962  return std::move(
963  atomic_load(reinterpret_cast<const std::shared_ptr<T> *>(p)));
964 }
965 
966 /** \brief Returns the shared pointer pointed-to by p.
967  *
968  * As with the non-specialized std::atomic_load_explicit, mo cannot be
969  * std::memory_order_release or std::memory_order_acq_rel
970  */
971 template <class T>
973  std::memory_order mo) {
974  return std::move(atomic_load_explicit(
975  reinterpret_cast<const std::shared_ptr<T> *>(p), mo));
976 }
977 
978 /** \brief Equivalent to atomic_store_explicit(p, r, memory_order_seq_cst)
979  */
980 template <class T> void atomic_store(shared_ptr<T> *p, shared_ptr<T> r) {
981  atomic_store(reinterpret_cast<std::shared_ptr<T> *>(p),
983 }
984 
985 /** \brief Stores the shared pointer r in the shared pointer pointed-to by p
986  * atomically, effectively executing p->swap(r).
987  *
988  * As with the non-specialized std::atomic_store_explicit, mo cannot be
989  * std::memory_order_acquire or std::memory_order_acq_rel.
990  */
991 template <class T>
993  std::memory_order mo) {
994  atomic_store_explicit(reinterpret_cast<std::shared_ptr<T> *>(p),
995  r.get_std_shared_ptr(), mo);
996 }
997 
998 /** \brief Equivalent to atomic_exchange(p, r, memory_order_seq_cst)
999  */
1000 template <class T>
1002  return std::move(atomic_exchange(reinterpret_cast<std::shared_ptr<T> *>(p),
1003  r.get_std_shared_ptr()));
1004 }
1005 
1006 /** \brief Stores the shared pointer r in the shared pointer pointed to by p and
1007  * returns the value formerly pointed-to by p, atomically.
1008  *
1009  * Effectively executes p->swap(r) and returns a copy of r after the swap.
1010  */
1011 template <class T>
1013  std::memory_order mo) {
1014  return std::move(
1015  atomic_exchange_explicit(reinterpret_cast<std::shared_ptr<T> *>(p),
1016  r.get_std_shared_ptr(), mo));
1017 }
1018 
1019 /** \brief Equivalent to atomic_compare_exchange_weak_explicit(p, expected,
1020  * desired, std::memory_order_seq_cst, std::memory_order_seq_cst)
1021  */
1022 template <class T>
1024  shared_ptr<T> desired) {
1026  reinterpret_cast<std::shared_ptr<T> *>(p),
1027  reinterpret_cast<std::shared_ptr<T> *>(expected),
1029 }
1030 
1031 /** \brief Equivalent to atomic_compare_exchange_strong_explicit(p, expected,
1032  * desired, std::memory_order_seq_cst, std::memory_order_seq_cst)
1033  */
1034 template <class T>
1036  shared_ptr<T> desired) {
1038  reinterpret_cast<std::shared_ptr<T> *>(p),
1039  reinterpret_cast<std::shared_ptr<T> *>(expected),
1041 }
1042 
1043 /** \brief Compares the shared pointers pointed-to by p and expected. If they
1044  * are equivalent (store the same pointer value, and either share ownership of
1045  * the same object or are both empty), assigns desired into *p using the memory
1046  * ordering constraints specified by success and returns true. If they are not
1047  * equivalent, assigns *p into *expected using the memory ordering constraints
1048  * specified by failure and returns false.
1049  */
1050 template <class T>
1052  shared_ptr<T> *expected,
1053  shared_ptr<T> desired,
1054  std::memory_order success,
1055  std::memory_order failure) {
1057  reinterpret_cast<std::shared_ptr<T> *>(p),
1058  reinterpret_cast<std::shared_ptr<T> *>(expected),
1060 }
1061 
1062 /** \brief Compares the shared pointers pointed-to by p and expected. If they
1063  * are equivalent (store the same pointer value, and either share ownership of
1064  * the same object or are both empty), assigns desired into *p using the memory
1065  * ordering constraints specified by success and returns true. If they are not
1066  * equivalent, assigns *p into *expected using the memory ordering constraints
1067  * specified by failure and returns false, but may fail spuriously.
1068  */
1069 template <class T>
1071  shared_ptr<T> *expected,
1072  shared_ptr<T> desired,
1073  std::memory_order success,
1074  std::memory_order failure) {
1076  reinterpret_cast<std::shared_ptr<T> *>(p),
1077  reinterpret_cast<std::shared_ptr<T> *>(expected),
1079 }
1080 #endif // atomic methods supported by compiler
1081 
1082 } // namespace throwing
1083 
1084 namespace std {
1085 
1086 /** \brief Template specialization of std::hash for throwing::shared_ptr<T>
1087  */
1088 template <class T> struct hash<throwing::shared_ptr<T>> {
1089  size_t operator()(const throwing::shared_ptr<T> &x) const {
1090  return std::hash<typename throwing::shared_ptr<T>::element_type *>()(
1091  x.get());
1092  }
1093 };
1094 
1095 } // namespace std
1096 
1097 #include <throwing/private/clear_compiler_checks.hpp>
bool operator<=(const shared_ptr< T > &lhs, const std::shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:826
shared_ptr(std::shared_ptr< T > &&r) TSP_NOEXCEPT
Move-constructs a shared_ptr from r.
Definition: shared_ptr.hpp:200
bool atomic_is_lock_free(shared_ptr< T > const *p)
Determines whether atomic access to the shared pointer pointed-to by p is lock-free.
Definition: shared_ptr.hpp:955
shared_ptr(Y *ptr, Deleter d)
Constructs a shared_ptr with ptr as the pointer to the managed object.
Definition: shared_ptr.hpp:98
bool operator>=(const shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:723
shared_ptr< T > static_pointer_cast(const shared_ptr< U > &r) TSP_NOEXCEPT
Creates a new instance of shared_ptr whose stored pointer is obtained from r&#39;s stored pointer using a...
Definition: shared_ptr.hpp:599
shared_ptr< T > const_pointer_cast(const shared_ptr< U > &r) TSP_NOEXCEPT
Creates a new instance of shared_ptr whose stored pointer is obtained from r&#39;s stored pointer using a...
Definition: shared_ptr.hpp:638
bool operator>=(const std::shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:779
shared_ptr< T > atomic_exchange(shared_ptr< T > *p, shared_ptr< T > r)
Equivalent to atomic_exchange(p, r, memory_order_seq_cst)
shared_ptr(std::shared_ptr< Y > &&r) TSP_NOEXCEPT
Move-constructs a shared_ptr from r.
Definition: shared_ptr.hpp:208
#define TSP_CONSTEXPR
bool operator==(const shared_ptr< T > &lhs, const std::shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:788
bool operator<(const shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:696
bool operator!=(const shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:685
shared_ptr & operator=(std::unique_ptr< Y, Deleter > &&r)
Assignment operator.
Definition: shared_ptr.hpp:337
shared_ptr & operator=(shared_ptr< Y > &&r) TSP_NOEXCEPT
Assignment operator.
Definition: shared_ptr.hpp:319
bool operator>=(const shared_ptr< T > &lhs, const std::shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:835
shared_ptr & operator=(shared_ptr &&r) TSP_NOEXCEPT
Assignment operator.
Definition: shared_ptr.hpp:303
bool operator!=(const shared_ptr< T > &lhs, std::nullptr_t rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:860
shared_ptr(Y *ptr)
Constructs a shared_ptr with ptr as the pointer to the managed object.
Definition: shared_ptr.hpp:84
Deleter * get_deleter(const shared_ptr< T > &p) TSP_NOEXCEPT
Access to the p&#39;s deleter.
Definition: shared_ptr.hpp:668
shared_ptr(std::unique_ptr< Y, Deleter > &&r)
Constructs a shared_ptr which manages the object currently managed by r.
Definition: shared_ptr.hpp:243
bool atomic_compare_exchange_weak_explicit(shared_ptr< T > *p, shared_ptr< T > *expected, shared_ptr< T > desired, std::memory_order success, std::memory_order failure)
Compares the shared pointers pointed-to by p and expected. If they are equivalent (store the same poi...
shared_ptr< T > atomic_load_explicit(const shared_ptr< T > *p, std::memory_order mo)
Returns the shared pointer pointed-to by p.
Definition: shared_ptr.hpp:972
bool operator<(const shared_ptr< T > &lhs, std::nullptr_t rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:876
shared_ptr(shared_ptr &&r) TSP_NOEXCEPT
Move-constructs a shared_ptr from r.
Definition: shared_ptr.hpp:170
operator bool() const TSP_NOEXCEPT
Checks if *this stores a non-null pointer, i.e. whether get() != nullptr.
Definition: shared_ptr.hpp:475
const std::shared_ptr< T > & get_std_shared_ptr() const TSP_NOEXCEPT
Returns the underlying std::shared_pointer.
Definition: shared_ptr.hpp:411
shared_ptr< T > atomic_exchange_explicit(shared_ptr< T > *p, shared_ptr< T > r, std::memory_order mo)
Stores the shared pointer r in the shared pointer pointed to by p and returns the value formerly poin...
shared_ptr & operator=(const shared_ptr< Y > &r) TSP_NOEXCEPT
Assignment operator.
Definition: shared_ptr.hpp:287
bool operator==(std::nullptr_t lhs, const shared_ptr< T > &rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:852
bool operator>=(std::nullptr_t lhs, const shared_ptr< T > &rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:932
std::shared_ptr< T >::element_type element_type
the type pointed to.
Definition: shared_ptr.hpp:66
#define TSP_NOEXCEPT
size_t operator()(const throwing::shared_ptr< T > &x) const
bool atomic_compare_exchange_weak(shared_ptr< T > *p, shared_ptr< T > *expected, shared_ptr< T > desired)
Equivalent to atomic_compare_exchange_weak_explicit(p, expected, desired, std::memory_order_seq_cst, std::memory_order_seq_cst)
shared_ptr(const shared_ptr &r) TSP_NOEXCEPT
Constructs a shared_ptr which shares ownership of the object managed by r.
Definition: shared_ptr.hpp:155
shared_ptr< T > dynamic_pointer_cast(const shared_ptr< U > &r) TSP_NOEXCEPT
Creates a new instance of shared_ptr whose stored pointer is obtained from r&#39;s stored pointer using a...
Definition: shared_ptr.hpp:618
long use_count() const TSP_NOEXCEPT
Returns the number of different shared_ptr instances (this included) managing the current object...
Definition: shared_ptr.hpp:470
bool operator!=(const shared_ptr< T > &lhs, const std::shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:797
Wrapper aroung std::shared_ptr that throws when a wrapped null pointer is dereferenced.
Definition: shared_ptr.hpp:63
bool operator!=(const std::shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:741
shared_ptr(Y *ptr, Deleter d, Alloc alloc)
Constructs a shared_ptr with ptr as the pointer to the managed object.
Definition: shared_ptr.hpp:130
bool operator>=(const shared_ptr< T > &lhs, std::nullptr_t rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:924
bool owner_before(const shared_ptr< Y > &other) const TSP_NOEXCEPT
Checks whether this shared_ptr precedes other in implementation defined owner-based (as opposed to va...
Definition: shared_ptr.hpp:489
bool atomic_compare_exchange_strong(shared_ptr< T > *p, shared_ptr< T > *expected, shared_ptr< T > desired)
Equivalent to atomic_compare_exchange_strong_explicit(p, expected, desired, std::memory_order_seq_cst...
shared_ptr< T > reinterpret_pointer_cast(const shared_ptr< U > &r) TSP_NOEXCEPT
Creates a new instance of shared_ptr whose stored pointer is obtained from r&#39;s stored pointer using a...
Definition: shared_ptr.hpp:655
bool operator==(const shared_ptr< T > &lhs, std::nullptr_t rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:844
bool operator<=(std::nullptr_t lhs, const shared_ptr< T > &rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:916
bool operator!=(std::nullptr_t lhs, const shared_ptr< T > &rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:868
Implementations of throwing::shared_ptr, throwing::unique_ptr and related.
bool owner_before(const std::shared_ptr< Y > &other) const TSP_NOEXCEPT
Checks whether this shared_ptr precedes other in implementation defined owner-based (as opposed to va...
Definition: shared_ptr.hpp:505
~shared_ptr()=default
Destructor If *this owns an object and it is the last shared_ptr owning it, the object is destroyed t...
element_type * get() const TSP_NOEXCEPT
Returns the stored pointer.
Definition: shared_ptr.hpp:407
shared_ptr< T > atomic_load(const shared_ptr< T > *p)
Equivalent to atomic_load_explicit(p, std::memory_order_seq_cst)
Definition: shared_ptr.hpp:961
bool operator<=(const std::shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:770
bool operator>(const shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:705
#define TSP_ARRAY_SUPPORT
bool operator==(const std::shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:732
T & operator*() const
Dereferences the stored pointer.
Definition: shared_ptr.hpp:423
void swap(shared_ptr &r) TSP_NOEXCEPT
Exchanges the contents of *this and r.
Definition: shared_ptr.hpp:344
TSP_CONSTEXPR shared_ptr(std::nullptr_t ptr) TSP_NOEXCEPT
Constructs a shared_ptr with no managed object, i.e. empty shared_ptr.
Definition: shared_ptr.hpp:79
shared_ptr(const shared_ptr< Y > &r, element_type *ptr) TSP_NOEXCEPT
The aliasing constructor.
Definition: shared_ptr.hpp:147
bool operator>(std::nullptr_t lhs, const shared_ptr< T > &rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:900
shared_ptr(const shared_ptr< Y > &r) TSP_NOEXCEPT
Constructs a shared_ptr which shares ownership of the object managed by r.
Definition: shared_ptr.hpp:163
bool owner_before(const std::weak_ptr< Y > &other) const TSP_NOEXCEPT
Checks whether this shared_ptr precedes other in implementation defined owner-based (as opposed to va...
Definition: shared_ptr.hpp:521
shared_ptr(const std::shared_ptr< T > &r) TSP_NOEXCEPT
Constructs a shared_ptr which shares ownership of the object managed by r.
Definition: shared_ptr.hpp:185
shared_ptr(const std::shared_ptr< Y > &r) TSP_NOEXCEPT
Constructs a shared_ptr which shares ownership of the object managed by r.
Definition: shared_ptr.hpp:193
bool atomic_compare_exchange_strong_explicit(shared_ptr< T > *p, shared_ptr< T > *expected, shared_ptr< T > desired, std::memory_order success, std::memory_order failure)
Compares the shared pointers pointed-to by p and expected. If they are equivalent (store the same poi...
T * operator->() const
Dereferences the stored pointer.
Definition: shared_ptr.hpp:434
shared_ptr(std::nullptr_t ptr, Deleter d)
Constructs a shared_ptr with ptr as the pointer to the managed object.
Definition: shared_ptr.hpp:112
bool operator<(const shared_ptr< T > &lhs, const std::shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:808
void reset(Y *ptr, Deleter d)
Replaces the managed object with an object pointed to by ptr.
Definition: shared_ptr.hpp:381
shared_ptr< T > make_shared(Args &&... args)
Constructs an object of type T and wraps it in a throwing::shared_ptr using args as the parameter lis...
Definition: shared_ptr.hpp:557
bool operator<=(const shared_ptr< T > &lhs, std::nullptr_t rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:908
void reset(Y *ptr)
Replaces the managed object with an object pointed to by ptr.
Definition: shared_ptr.hpp:368
bool operator>(const shared_ptr< T > &lhs, std::nullptr_t rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:892
TSP_CONSTEXPR shared_ptr() TSP_NOEXCEPT=default
Constructs a shared_ptr with no managed object, i.e. empty shared_ptr.
shared_ptr< T > allocate_shared(const Alloc &alloc, Args &&... args)
Constructs an object of type T and wraps it in a throwing::shared_ptr using args as the parameter lis...
Definition: shared_ptr.hpp:583
void swap(throwing::shared_ptr< T > &lhs, throwing::shared_ptr< T > &rhs) TSP_NOEXCEPT
Specializes the std::swap algorithm for throwing::shared_ptr.
Definition: shared_ptr.hpp:536
bool operator>(const shared_ptr< T > &lhs, const std::shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:817
shared_ptr(const std::weak_ptr< Y > &r)
Constructs a shared_ptr which shares ownership of the object managed by r.
Definition: shared_ptr.hpp:223
void atomic_store(shared_ptr< T > *p, shared_ptr< T > r)
Equivalent to atomic_store_explicit(p, r, memory_order_seq_cst)
Definition: shared_ptr.hpp:980
shared_ptr & operator=(const shared_ptr &r) TSP_NOEXCEPT
Assignment operator.
Definition: shared_ptr.hpp:270
std::shared_ptr< T > & get_std_shared_ptr() TSP_NOEXCEPT
Returns the underlying std::shared_pointer.
Definition: shared_ptr.hpp:417
bool operator>(const std::shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:761
bool operator<(const std::shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:752
bool operator==(const shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:676
void reset(Y *ptr, Deleter d, Alloc alloc)
Replaces the managed object with an object pointed to by ptr.
Definition: shared_ptr.hpp:401
void reset() TSP_NOEXCEPT
Releases the ownership of the managed object, if any.
Definition: shared_ptr.hpp:356
shared_ptr(shared_ptr< Y > &&r) TSP_NOEXCEPT
Move-constructs a shared_ptr from r.
Definition: shared_ptr.hpp:178
void atomic_store_explicit(shared_ptr< T > *p, shared_ptr< T > r, std::memory_order mo)
Stores the shared pointer r in the shared pointer pointed-to by p atomically, effectively executing p...
Definition: shared_ptr.hpp:992
bool operator<=(const shared_ptr< T > &lhs, const shared_ptr< U > &rhs) TSP_NOEXCEPT
Compare two shared_ptr objects.
Definition: shared_ptr.hpp:714
bool operator<(std::nullptr_t lhs, const shared_ptr< T > &rhs) TSP_NOEXCEPT
Compare a shared_ptr with a null pointer.
Definition: shared_ptr.hpp:884