This paper provides wording to the effect that it creates independent fundamental-ts types in namespace std::experimental for shared_ptr, weak_ptr, owner_less, enable_shared_from_this, and all relevant functions and hash specializations.
Currently, the fundamental-ts refers to std::shared_ptr and std::weak_ptr and has applied extensions to those existing C++11 types, which has caused some significant concerns, which are in described in N4041.
As a consequence of discussing this paper ("Guidelines for the contents of Technical Specifications") and performing straw polls within LEWG the following direction was requested:shared_ptr<array> in TS in std::experimental? (shared_ptr<non-array> would also be copied to std::experimental)
SF-F-N-A-SA
4-9-6-1-0
This proposal attempts to provide wording to realize these effects.
Note to the editor: The intention is simply to create new types (and related functions) in namespace std::experimental::fundamentals_v1 with the same behaviour as was specified for std::shared_ptr and std::weak_ptr by the previous draft of the Library Fundamentals TS. Any other differences introduced by this paper are unintentional and should be considered editorial, not part of the proposal.
The proposed wording changes refer to N4023.
Modify Table 2 — "Significant features in this technical specification" as indicated:
Table 2 — Significant features in this technical specification Doc.
No.Title Primary
SectionMacro Name Suffix Value Header … N3920
Extending shared_ptr to Support Arrays 2.3 [mods.util.smartptr.shared]
8.2 [memory.smartptr]shared_ptr_arrays 201402 <experimental/memory> …
Remove the existing sub-clause 2.2 [mods.util.smartptr.shared] in its entirety:
2.2 Changes to std::shared_ptr and std::weak_ptr [mods.util.smartptr.shared]
-1- Make the following changes in C++14 §20.8.2.2 […]
[…]
-5- For the purposes of subclause C++14 §20.8.2, […]
2.2.1 Changes to std::shared_ptr constructors [mods.util.smartptr.shared.const]
-1- Make the following changes in C++14 §20.8.2.2.1 […]
[…]
-36- Exception safety: If an exception is thrown, […]
2.2.2 Changes to std::shared_ptr observers [mods.util.smartptr.shared.obs]
-1- Make the following changes in C++14 §20.8.2.2.5 […]
[…]
Remarks: When T is not an array type, […]
2.2.3 Changes to std::shared_ptr casts [mods.util.smartptr.shared.cast]
-1- Make the following changes in C++14 §20.8.2.2.9 […]
[…]
-16- [Note: The seemingly equivalent expression […] - end note]
2.2.4 Changes to std::weak_ptr [mods.util.smartptr.weak]
-1- Make the following changes in C++14 §20.8.2.3 […]
[…]
-6- [Postconditions: use_count() == r.use_count().
Change header <experimental/memory> synopsis, 8.1 [header.memory.synop], as indicated:
#include <memory> namespace std { namespace experimental { inline namespace fundamentals_v1 { // See C++14 §20.7.7, uses_allocator template <class T, class Alloc> constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value;// 8.2.1 Class template shared_ptr: template<class T> class shared_ptr; // See C++14 §20.8.2.2.6 shared_ptr creation template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); template<class T, class A, class... Args> shared_ptr<T> allocate_shared(const A& a, Args&&... args); // See C++14 §20.8.2.2.7 shared_ptr comparison template<class T, class U> bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template<class T, class U> bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept; template <class T> bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator==(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator!=(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator<=(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>(nullptr_t, const shared_ptr<T>& b) noexcept; template <class T> bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept; template <class T> bool operator>=(nullptr_t, const shared_ptr<T>& b) noexcept; // See C++14 §20.8.2.2.8 shared_ptr specialized algorithms template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;// 8.2.1.3, shared_ptr caststemplate<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept; template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>const& r) noexcept;// C++14 §20.8.2.2.10 get_deleter template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept; // C++14 §20.8.2.2.11 shared_ptr I/O template<class E, class T, class Y> basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p); // 8.2.2 Class template weak_ptr template<class T> class weak_ptr; // C++14 §20.8.2.3.6 weak_ptr specialized algorithms template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept; // C++14 §20.8.2.4 Class template owner_less template<class T> class owner_less; // C++14 §20.8.2.5 Class template enable_shared_from_this template<class T> class enable_shared_from_this; // C++14 §20.8.2.6 shared_ptr atomic access template<class T> bool atomic_is_lock_free(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load(const shared_ptr<T>* p); template<class T> shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo); template<class T> void atomic_store(shared_ptr<T>* p, shared_ptr<T> r); template<class T> void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r); template<class T> shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo); template<class T> bool atomic_compare_exchange_weak( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_strong( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w); template<class T> bool atomic_compare_exchange_weak_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure); template<class T> bool atomic_compare_exchange_strong_explicit( shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w, memory_order success, memory_order failure);} // namespace fundamentals_v1 } // namespace experimental // C++14 §20.8.2.7 Smart pointer hash support template<class T> struct hash<experimental::shared_ptr<T>>; }
Replace section 8.2 [memory.smartptr.shared.cast] as shown:
8.2 shared_ptr casts [memory.smartptr.shared.cast]
-1- template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
-2- Requires: The expression reinterpret_cast<T*>((U*)0) shall be well formed.
-3- Returns: shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get())).
8.2 Shared-ownership pointers [memory.smartptr]
-1- The specification of all declarations within this sub-clause [memory.smartptr] and its sub-clauses are the same as the corresponding declarations, as specified in C++14 §20.8.2 [util.smartptr], unless explicitly specified otherwise.
8.2.1 Class template shared_ptr [memory.smartptr.shared]
namespace std {
namespace experimental {
inline namespace fundamentals_v1 {
template<class T> class shared_ptr {
public:
typedef typename remove_extent<T>::type element_type;
// 8.2.1.1 shared_ptr constructors
constexpr shared_ptr() noexcept;
template<class Y> explicit shared_ptr(Y* p);
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d)
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;
shared_ptr(const shared_ptr& r) noexcept;
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
shared_ptr(shared_ptr&& r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
template<class Y> shared_ptr(auto_ptr<Y>&& r);
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
constexpr shared_ptr(nullptr_t) : shared_ptr() { }
// C++14 §20.8.2.2.2 [util.smartptr.shared.dest]
~shared_ptr();
// C++14 §20.8.2.2.3 [util.smartptr.shared.assign]
shared_ptr& operator=(const shared_ptr& r) noexcept;
template<class Y> shared_ptr& operator=(const shared_ptr<Y>& r) noexcept;
shared_ptr& operator=(shared_ptr&& r) noexcept;
template<class Y> shared_ptr& operator=(shared_ptr<Y>&& r) noexcept;
template<class Y> shared_ptr& operator=(auto_ptr<Y>&& r);
template <class Y, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
// C++14 §20.8.2.2.4 [util.smartptr.shared.mod]
void swap(shared_ptr& r) noexcept;
void reset() noexcept;
template<class Y> void reset(Y* p);
template<class Y, class D> void reset(Y* p, D d);
template<class Y, class D, class A> void reset(Y* p, D d, A a);
// 8.2.1.2 shared_ptr observers
element_type* get() const noexcept;
T& operator*() const noexcept;
T* operator->() const noexcept;
element_type& operator[](ptrdiff_t i) const noexcept;
long use_count() const noexcept;
bool unique() const noexcept;
explicit operator bool() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
};
// See C++14 §20.8.2.2.6 shared_ptr creation
template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
template<class T, class A, class... Args>
shared_ptr<T> allocate_shared(const A& a, Args&&... args);
// See C++14 §20.8.2.2.7 shared_ptr comparison
template<class T, class U>
bool operator==(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
template<class T, class U>
bool operator!=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
template<class T, class U>
bool operator<(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
template<class T, class U>
bool operator>(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
template<class T, class U>
bool operator<=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
template<class T, class U>
bool operator>=(const shared_ptr<T>& a, const shared_ptr<U>& b) noexcept;
template <class T>
bool operator==(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator==(nullptr_t, const shared_ptr<T>& b) noexcept;
template <class T>
bool operator!=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator!=(nullptr_t, const shared_ptr<T>& b) noexcept;
template <class T>
bool operator<(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator<(nullptr_t, const shared_ptr<T>& b) noexcept;
template <class T>
bool operator<=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator<=(nullptr_t, const shared_ptr<T>& b) noexcept;
template <class T>
bool operator>(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator>(nullptr_t, const shared_ptr<T>& b) noexcept;
template <class T>
bool operator>=(const shared_ptr<T>& a, nullptr_t) noexcept;
template <class T>
bool operator>=(nullptr_t, const shared_ptr<T>& b) noexcept;
// See C++14 §20.8.2.2.8 shared_ptr specialized algorithms
template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
// 8.2.1.3, shared_ptr casts
template<class T, class U>
shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
template<class T, class U>
shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
// C++14 §20.8.2.2.10 get_deleter
template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
// C++14 §20.8.2.2.11 shared_ptr I/O
template<class E, class T, class Y>
basic_ostream<E, T>& operator<< (basic_ostream<E, T>& os, const shared_ptr<Y>& p);
// C++14 §20.8.2.4 Class template owner_less
template<class T> class owner_less;
// C++14 §20.8.2.5 Class template enable_shared_from_this
template<class T> class enable_shared_from_this;
// C++14 §20.8.2.6 shared_ptr atomic access
template<class T>
bool atomic_is_lock_free(const shared_ptr<T>* p);
template<class T>
shared_ptr<T> atomic_load(const shared_ptr<T>* p);
template<class T>
shared_ptr<T> atomic_load_explicit(const shared_ptr<T>* p, memory_order mo);
template<class T>
void atomic_store(shared_ptr<T>* p, shared_ptr<T> r);
template<class T>
void atomic_store_explicit(shared_ptr<T>* p, shared_ptr<T> r, memory_order mo);
template<class T>
shared_ptr<T> atomic_exchange(shared_ptr<T>* p, shared_ptr<T> r);
template<class T>
shared_ptr<T> atomic_exchange_explicit(shared_ptr<T>* p, shared_ptr<T> r,
memory_order mo);
template<class T>
bool atomic_compare_exchange_weak(
shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T>
bool atomic_compare_exchange_strong(
shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w);
template<class T>
bool atomic_compare_exchange_weak_explicit(
shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w,
memory_order success, memory_order failure);
template<class T>
bool atomic_compare_exchange_strong_explicit(
shared_ptr<T>* p, shared_ptr<T>* v, shared_ptr<T> w,
memory_order success, memory_order failure);
} // namespace fundamentals_v1
} // namespace experimental
// C++14 §20.8.2.7 Smart pointer hash support
template<class T> struct hash<experimental::shared_ptr<T>>;
} // namespace std
-1- For the purposes of subclause [memory.smartptr], a pointer type
Y*
is said to be compatible with a pointer typeT*
when eitherY*
is convertible toT*
orY
isU[N]
andT
isU cv []
.
8.2.1.1 shared_ptr
constructors [memory.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
-1- Requires:
Y
shall be a complete type. The expressiondelete[] p
, whenT
is an array type, ordelete p
, whenT
is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. WhenT
isU[N]
,Y(*)[N]
shall be convertible toT*
; whenT
isU[]
,Y(*)[]
shall be convertible toT*
; otherwise,Y*
shall be convertible toT*
.-2- Effects: When
T
is not an array type, constructs ashared_ptr
object that owns the pointerp
. Otherwise, constructs ashared_ptr
that ownsp
and a deleter of an unspecified type that callsdelete[] p
.-3- Postconditions:
use_count() == 1 && get() == p
.-4- Throws:
bad_alloc
, or an implementation-defined exception when a resource other than memory could not be obtained.-5- Exception safety: If an exception is thrown,
delete p
is called whenT
is not an array type,delete[] p
otherwise.
template<class Y, class D> shared_ptr(Y* p, D d);
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template <class D> shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);
template<class Y> shared_ptr(const shared_ptr<Y>& r, element_type* p) noexcept;-1- Requires:
D
shall beCopyConstructible
. The copy constructor and destructor ofD
shall not throw exceptions. The expressiond(p)
shall be well formed, shall have well defined behavior, and shall not throw exceptions.A
shall be an allocator (C++14 §17.6.3.5 [allocator.requirements]). The copy constructor and destructor ofA
shall not throw exceptions. WhenT
isU[N]
,Y(*)[N]
shall be convertible toT*
; whenT
isU[]
,Y(*)[]
shall be convertible toT*
; otherwise,Y*
shall be convertible toT*
.-2- Effects: Constructs a
shared_ptr
object that owns the objectp
and the deleterd
. The second and fourth constructors shall use a copy ofa
to allocate memory for internal use.-3- Postconditions:
use_count() == 1 && get() == p
.-4- Throws:
bad_alloc
, or an implementation-defined exception when a resource other than memory could not be obtained.-5- Exception safety: If an exception is thrown,
d(p)
is called.
-1- Effects: Constructs a
shared_ptr
instance that storesp
and shares ownership withr
.-2- Postconditions:
get() == p && use_count() == r.use_count()
-3- [Note: To avoid the possibility of a dangling pointer, the user of this constructor must ensure that
p
remains valid at least until the ownership group ofr
is destroyed. -end note]-4- [Note: This constructor allows creation of an empty
shared_ptr
instance with a non-null stored pointer. -end note]
shared_ptr(const shared_ptr& r) noexcept;
template<class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
-1- Requires: The second constructor shall not participate in the overload resolution unless
Y*
is compatible withT*
.-2- Effects: If
r
is empty, constructs an emptyshared_ptr
object; otherwise, constructs ashared_ptr
object that shares ownership withr
.-3- Postconditions:
get() == r.get() && use_count() == r.use_count()
.
shared_ptr(shared_ptr&& r) noexcept;
template<class Y> shared_ptr(shared_ptr<Y>&& r) noexcept;
-1- Remarks: The second constructor shall not participate in overload resolution unless
Y*
is compatible withT*
.-2- Effects: Move-constructs a
shared_ptr
instance fromr
.-3- Postconditions:
*this
shall contain the old value ofr
.r
shall be empty.r.get() == 0.
template<class Y> explicit shared_ptr(const weak_ptr<Y>& r);
-1- Requires:
Y*
shall be compatible withT*
.-2- Effects: Constructs a
shared_ptr
object that shares ownership withr
and stores a copy of the pointer stored inr
.-3- Postconditions:
use_count() == r.use_count()
.-4- Throws:
bad_weak_ptr
whenr.expired()
.-5- Exception safety: If an exception is thrown, the constructor has no effect.
template <class Y, class D> shared_ptr(unique_ptr<Y, D>&& r);
-1- Requires:
Y*
shall be compatible withT*
.-2- Effects: Equivalent to
shared_ptr(r.release(), r.get_deleter())
whenD
is not a reference type, otherwiseshared_ptr(r.release(), ref(r.get_deleter()))
.-3- Exception safety: If an exception is thrown, the constructor has no effect.
8.2.1.2 shared_ptr
observers [memory.smartptr.shared.obs]
element_type* get() const noexcept;
-1- Returns: the stored pointer.
T& operator*() const noexcept;
-1- Requires:
get() != 0
.-2- Returns:
*get()
.-3- Notes: When
T
is an array type or cv-qualifiedvoid
, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
T* operator->() const noexcept;
-1- Requires:
get() != 0
.-2- Returns:
get()
.-3- Remarks: When
T
is an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
element_type& operator[](ptrdiff_t i) const noexcept;
-1- Requires:
get() != 0 && i >= 0
. IfT
isU[N]
,i < N
.-2- Returns:
get()[i]
.-3- Remarks: When
T
is not an array type, it is unspecified whether this member function is declared. If it is declared, it is unspecified what its return type is, except that the declaration (although not necessarily the definition) of the function shall be well formed.
8.2.1.3 shared_ptr
casts [memory.smartptr.shared.cast]
template<class T, class U> shared_ptr<T> static_pointer_cast(const shared_ptr<U>& r) noexcept;
-1- Requires: The expression
static_cast<T*>((U*)0)
shall be well formed.-2- Returns:
shared_ptr<T>(r, static_cast<typename shared_ptr<T>::element_type*>(r.get()))
-3- [Note: The seemingly equivalent expression
shared_ptr<T>(static_cast<T*>(r.get()))
will eventually result in undefined behavior, attempting to delete the same object twice. -end note]
template<class T, class U> shared_ptr<T> dynamic_pointer_cast(const shared_ptr<U>& r) noexcept;
-1- Requires: The expression
dynamic_cast<T*>((U*)0)
shall be well formed.-2- Returns:
- When
dynamic_cast<typename shared_ptr<T>::element_type*>(r.get())
returns a nonzero valuep
,shared_ptr<T>(r, p)
;- Otherwise,
shared_ptr<T>()
.-3- [Note: The seemingly equivalent expression
shared_ptr<T>(dynamic_cast<T*>(r.get()))
will eventually result in undefined behavior, attempting to delete the same object twice. -end note]
template<class T, class U> shared_ptr<T> const_pointer_cast(const shared_ptr<U>& r) noexcept;
-1- Requires: The expression
const_cast<T*>((U*)0)
shall be well formed.-2- Returns:
shared_ptr<T>(r, const_cast<typename shared_ptr<T>::element_type*>(r.get()))
.-3- [Note: The seemingly equivalent expression
shared_ptr<T>(const_cast<T*>(r.get()))
will eventually result in undefined behavior, attempting to delete the same object twice. -end note]
template<class T, class U> shared_ptr<T> reinterpret_pointer_cast(const shared_ptr<U>& r) noexcept;
-1- Requires: The expression
reinterpret_cast<T*>((U*)0)
shall be well formed.-2- Returns:
shared_ptr<T>(r, reinterpret_cast<typename shared_ptr<T>::element_type*>(r.get()))
.
8.2.2 Class template weak_ptr [memory.smartptr.weak]
namespace std {
namespace experimental {
inline namespace fundamentals_v1 {
template<class T> class weak_ptr {
public:
typedef typename remove_extent<T>::type element_type;
// 8.2.2.1 weak_ptr constructors [memory.smartptr.weak.const]
constexpr weak_ptr() noexcept;
template<class Y> weak_ptr(shared_ptr<Y> const& r) noexcept;
weak_ptr(weak_ptr const& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y> const& r) noexcept;
weak_ptr(weak_ptr&& r) noexcept;
template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
// C++14 §20.8.2.3.2 [util.smartptr.weak.dest]
~weak_ptr();
// C++14 §20.8.2.3.3 [util.smartptr.weak.assign]
weak_ptr& operator=(weak_ptr const& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y> const& r) noexcept;
template<class Y> weak_ptr& operator=(shared_ptr<Y> const& r) noexcept;
weak_ptr& operator=(weak_ptr&& r) noexcept;
template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
// C++14 §20.8.2.3.4 [util.smartptr.weak.mod]
void swap(weak_ptr& r) noexcept;
void reset() noexcept;
// C++14 §20.8.2.3.5 [util.smartptr.weak.obs]
long use_count() const noexcept;
bool expired() const noexcept;
shared_ptr<T> lock() const noexcept;
template<class U> bool owner_before(shared_ptr<U> const& b) const;
template<class U> bool owner_before(weak_ptr<U> const& b) const;
};
// C++14 §20.8.2.3.6 weak_ptr specialized algorithms
template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
} // namespace fundamentals_v1
} // namespace experimental
} // namespace std
8.2.2.1 weak_ptr
constructors [memory.smartptr.weak.const]
weak_ptr(const weak_ptr& r) noexcept;
template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
-1- Requires: The second and third constructors shall not participate in the overload resolution unless
Y*
is compatible withT*
.-2- Effects: If
r
is empty, constructs an emptyweak_ptr
object; otherwise, constructs aweak_ptr
object that shares ownership withr
and stores a copy of the pointer stored inr
.-3- Postconditions:
use_count() == r.use_count()
.