Experimental shared_ptr for Library Fundamentals TS (original) (raw)

-1- template<class T, class U> shared_ptr reinterpret_pointer_cast(const shared_ptr& r) noexcept;

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 type T* when either Y* is convertible to T* or Y is U[N] and T is U cv [].

8.2.1.1 shared_ptr constructors [memory.smartptr.shared.const]

template explicit shared_ptr(Y* p);

-1-Requires: Y shall be a complete type. The expression delete[] p, when T is an array type, or delete p, when T is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. When T is U[N], Y(*)[N] shall be convertible to T*; when T is U[], Y(*)[] shall be convertible to T*; otherwise, Y* shall be convertible to T*.

-2- Effects: When T is not an array type, constructs a shared_ptr object that owns the pointer p. Otherwise, constructs a shared_ptr that owns p and a deleter of an unspecified type that calls delete[] 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 when T 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 shared_ptr(nullptr_t p, D d);
template <class D, class A> shared_ptr(nullptr_t p, D d, A a);

-1-Requires: D shall be CopyConstructible. The copy constructor and destructor of D shall not throw exceptions. The expression d(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 of A shall not throw exceptions. When T is U[N], Y(*)[N] shall be convertible to T*; when T is U[], Y(*)[] shall be convertible to T*; otherwise, Y* shall be convertible to T*.

-2- Effects: Constructs a shared_ptr object that owns the object p and the deleter d. The second and fourth constructors shall use a copy of a 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.

template shared_ptr(const shared_ptr& r, element_type* p) noexcept;

-1- Effects: Constructs a shared_ptr instance that stores p and shares ownership with r.

-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 of r 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 shared_ptr(const shared_ptr& r) noexcept;

-1-Requires: The second constructor shall not participate in the overload resolution unless Y* is compatible with T*.

-2- Effects: If r is empty, constructs an empty shared_ptr object; otherwise, constructs a shared_ptr object that shares ownership with r.

-3- Postconditions: get() == r.get() && use_count() == r.use_count().

shared_ptr(shared_ptr&& r) noexcept;
template shared_ptr(shared_ptr&& r) noexcept;

-1-Remarks: The second constructor shall not participate in overload resolution unless Y* is compatible with T*.

-2- Effects: Move-constructs a shared_ptr instance from r.

-3- Postconditions: *this shall contain the old value of r. r shall be empty. r.get() == 0.

template explicit shared_ptr(const weak_ptr& r);

-1-Requires: Y* shall be compatible with T*.

-2- Effects: Constructs a shared_ptr object that shares ownership with r and stores a copy of the pointer stored in r.

-3- Postconditions: use_count() == r.use_count().

-4- Throws: bad_weak_ptr when r.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 with T*.

-2- Effects: Equivalent to shared_ptr(r.release(), r.get_deleter()) when D is not a reference type, otherwise shared_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-qualified void, 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. If T is U[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 static_pointer_cast(const shared_ptr& 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 dynamic_pointer_cast(const shared_ptr& r) noexcept;

-1-Requires: The expression dynamic_cast<T*>((U*)0) shall be well formed.

-2- Returns:

-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 const_pointer_cast(const shared_ptr& 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 reinterpret_pointer_cast(const shared_ptr& 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 weak_ptr(const weak_ptr& r) noexcept;
template weak_ptr(const shared_ptr& r) noexcept;

-1-Requires: The second and third constructors shall not participate in the overload resolution unless Y* is compatible with T*.

-2- Effects: If r is empty, constructs an empty weak_ptr object; otherwise, constructs a weak_ptr object that shares ownership with r and stores a copy of the pointer stored in r.

-3- Postconditions: use_count() == r.use_count().