Standard library header <memory>

From cppreference.com
< cpp‎ | header

This header is part of the dynamic memory management library.

Smart pointers categories
smart pointer with unique object ownership semantics
(class template)
smart pointer with shared object ownership semantics
(class template)
(C++11)
weak reference to an object managed by std::shared_ptr
(class template)
(until C++17)
smart pointer with strict object ownership semantics
(class template)
Helper classes
provides mixed-type owner-based ordering of shared and weak pointers
(class template)
allows an object to create a shared_ptr referring to itself
(class template)
exception thrown when accessing a weak_ptr which refers to already destroyed object
(class)
default deleter for unique_ptr
(class template)
Allocators
the default allocator
(class template)
provides information about allocator types
(class template)
tag type used to select allocator-aware constructor overloads
(class)
an object of type std::allocator_arg_t used to select allocator-aware constructors
(constant)
checks if the specified type supports uses-allocator construction
(class template)
Uninitialized storage
copies a range of objects to an uninitialized area of memory
(function template)
copies a number of objects to an uninitialized area of memory
(function template)
copies an object to an uninitialized area of memory, defined by a range
(function template)
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
moves a range of objects to an uninitialized area of memory
(function template)
moves a number of objects to an uninitialized area of memory
(function template)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
destroys an object at a given address
(function template)
(C++17)
destroys a range of objects
(function template)
(C++17)
destroys a number of objects in a range
(function template)
(deprecated in C++17)
an iterator that allows standard algorithms to store results in uninitialized memory
(class template)
(deprecated in C++17)
obtains uninitialized storage
(function template)
(deprecated in C++17)
frees uninitialized storage
(function template)
Garbage collector support
declares that an object can not be recycled
(function)
declares that an object can be recycled
(function template)
declares that a memory area does not contain traceable pointers
(function)
cancels the effect of std::declare_no_pointers
(function)
lists pointer safety models
(class)
returns the current pointer safety model
(function)
Miscellaneous
provides information about pointer-like types
(class template)
(C++11)
obtains actual address of an object, even if the & operator is overloaded
(function template)
(C++11)
aligns a pointer in a buffer
(function)
Smart pointer non-member operations
creates a unique pointer that manages a new object
(function template)
compares to another unique_ptr or with nullptr
(function template)
creates a shared pointer that manages a new object
(function template)
creates a shared pointer that manages a new object allocated using an allocator
(function template)
applies static_cast, dynamic_cast, const_cast, or reinterpret_cast to the stored pointer
(function template)
returns the deleter of specified type, if owned
(function template)
compares with another shared_ptr or with nullptr
(function template)
outputs the value of the stored pointer to an output stream
(function template)
specializes atomic operations for std::shared_ptr
(function template)
specializes the std::swap algorithm
(function template)
specializes the std::swap algorithm
(function template)
specializes the std::swap algorithm
(function template)
Smart pointer helper classes
hash support for std::unique_ptr
(class template specialization)
hash support for std::shared_ptr
(class template specialization)

Synopsis

namespace std {
  // pointer traits
  template <class Ptr> struct pointer_traits;
  template <class T> struct pointer_traits<T*>;
  // pointer safety
  enum class pointer_safety { relaxed, preferred, strict };
  void declare_reachable(void* p);
  template <class T> T* undeclare_reachable(T* p);
  void declare_no_pointers(char* p, size_t n);
  void undeclare_no_pointers(char* p, size_t n);
  pointer_safety get_pointer_safety() noexcept;
  // pointer alignment function
  void* align(size_t alignment, size_t size, void*& ptr, size_t& space);
  // allocator argument tag
  struct allocator_arg_t { explicit allocator_arg_t() = default; };
  constexpr allocator_arg_t allocator_arg{};
  // uses_allocator
  template <class T, class Alloc> struct uses_allocator;
  // allocator traits
  template <class Alloc> struct allocator_traits;
  // the default allocator
  template <class T> class allocator;
  template <class T, class U>
  bool operator==(const allocator<T>&, const allocator<U>&) noexcept;
  template <class T, class U>
  bool operator!=(const allocator<T>&, const allocator<U>&) noexcept;
  // specialized algorithms
  template <class T> constexpr T* addressof(T& r) noexcept;
  template <class T> const T* addressof(const T&&) = delete;
  template <class ForwardIterator>
  void uninitialized_default_construct(ForwardIterator first, ForwardIterator last);
  template <class ExecutionPolicy, class ForwardIterator>
  void uninitialized_default_construct(ExecutionPolicy&& exec,
                                       ForwardIterator first, ForwardIterator last);
  template <class ForwardIterator, class Size>
  ForwardIterator uninitialized_default_construct_n(ForwardIterator first, Size n);
  template <class ExecutionPolicy, class ForwardIterator, class Size>
  ForwardIterator uninitialized_default_construct_n(ExecutionPolicy&& exec,
                                                    ForwardIterator first, Size n);
  template <class ForwardIterator>
  void uninitialized_value_construct(ForwardIterator first, ForwardIterator last);
  template <class ExecutionPolicy, class ForwardIterator>
  void uninitialized_value_construct(ExecutionPolicy&& exec,
                                     ForwardIterator first, ForwardIterator last);
  template <class ForwardIterator, class Size>
  ForwardIterator uninitialized_value_construct_n(ForwardIterator first, Size n);
  template <class ExecutionPolicy, class ForwardIterator, class Size>
  ForwardIterator uninitialized_value_construct_n(ExecutionPolicy&& exec,
                                                  ForwardIterator first, Size n);
  template <class InputIterator, class ForwardIterator>
  ForwardIterator uninitialized_copy(InputIterator first, InputIterator last,
                                     ForwardIterator result);
  template <class ExecutionPolicy, class InputIterator, class ForwardIterator>
  ForwardIterator uninitialized_copy(ExecutionPolicy&& exec,
                                     InputIterator first, InputIterator last,
                                     ForwardIterator result);
  template <class InputIterator, class Size, class ForwardIterator>
  ForwardIterator uninitialized_copy_n(InputIterator first, Size n,
                                       ForwardIterator result);
  template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator>
  ForwardIterator uninitialized_copy_n(ExecutionPolicy&& exec,
                                       InputIterator first, Size n,
                                       ForwardIterator result);
  template <class InputIterator, class ForwardIterator>
  ForwardIterator uninitialized_move(InputIterator first, InputIterator last,
                                     ForwardIterator result);
  template <class ExecutionPolicy, class InputIterator, class ForwardIterator>
  ForwardIterator uninitialized_move(ExecutionPolicy&& exec,
                                     InputIterator first, InputIterator last,
                                     ForwardIterator result);
  template <class InputIterator, class Size, class ForwardIterator>
  pair<InputIterator, ForwardIterator>
    uninitialized_move_n(InputIterator first, Size n, ForwardIterator result);
  template <class ExecutionPolicy, class InputIterator, class Size, class ForwardIterator>
  pair<InputIterator, ForwardIterator>
    uninitialized_move_n(ExecutionPolicy&& exec,
                         InputIterator first, Size n, ForwardIterator result);
  template <class ForwardIterator, class T>
  void uninitialized_fill(ForwardIterator first, ForwardIterator last, const T& x);
  template <class ExecutionPolicy, class ForwardIterator, class T>
  void uninitialized_fill(ExecutionPolicy&& exec,
                          ForwardIterator first, ForwardIterator last, const T& x);
  template <class ForwardIterator, class Size, class T>
  ForwardIterator uninitialized_fill_n(ForwardIterator first, Size n, const T& x);
  template <class ExecutionPolicy, class ForwardIterator, class Size, class T>
  ForwardIterator uninitialized_fill_n(ExecutionPolicy&& exec,
                                       ForwardIterator first, Size n, const T& x);
  template <class T>
  void destroy_at(T* location);
  template <class ForwardIterator>
  void destroy(ForwardIterator first, ForwardIterator last);
  template <class ExecutionPolicy, class ForwardIterator>
  void destroy(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last);
  template <class ForwardIterator, class Size>
  ForwardIterator destroy_n(ForwardIterator first, Size n);
  template <class ExecutionPolicy, class ForwardIterator, class Size>
  ForwardIterator destroy_n(ExecutionPolicy&& exec, ForwardIterator first, Size n);
  // class template unique_ptr
  template <class T> struct default_delete;
  template <class T> struct default_delete<T[]>;
  template <class T, class D = default_delete<T>> class unique_ptr;
  template <class T, class D> class unique_ptr<T[], D>;
  template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);
  template <class T> unique_ptr<T> make_unique(size_t n);
  template <class T, class... Args> /*unspecified*/ make_unique(Args&&...) = delete;
  template <class T, class D> void swap(unique_ptr<T, D>& x, unique_ptr<T, D>& y) noexcept;
  template <class T1, class D1, class T2, class D2>
  bool operator==(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template <class T1, class D1, class T2, class D2>
  bool operator!=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template <class T1, class D1, class T2, class D2>
  bool operator<(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template <class T1, class D1, class T2, class D2>
  bool operator<=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template <class T1, class D1, class T2, class D2>
  bool operator>(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template <class T1, class D1, class T2, class D2>
  bool operator>=(const unique_ptr<T1, D1>& x, const unique_ptr<T2, D2>& y);
  template <class T, class D>
  bool operator==(const unique_ptr<T, D>& x, nullptr_t) noexcept;
  template <class T, class D>
  bool operator==(nullptr_t, const unique_ptr<T, D>& y) noexcept;
  template <class T, class D>
  bool operator!=(const unique_ptr<T, D>& x, nullptr_t) noexcept;
  template <class T, class D>
  bool operator!=(nullptr_t, const unique_ptr<T, D>& y) noexcept;
  template <class T, class D>
  bool operator<(const unique_ptr<T, D>& x, nullptr_t);
  template <class T, class D>
  bool operator<(nullptr_t, const unique_ptr<T, D>& y);
  template <class T, class D>
  bool operator<=(const unique_ptr<T, D>& x, nullptr_t);
  template <class T, class D>
  bool operator<=(nullptr_t, const unique_ptr<T, D>& y);
  template <class T, class D>
  bool operator>(const unique_ptr<T, D>& x, nullptr_t);
  template <class T, class D>
  bool operator>(nullptr_t, const unique_ptr<T, D>& y);
  template <class T, class D>
  bool operator>=(const unique_ptr<T, D>& x, nullptr_t);
  template <class T, class D>
  bool operator>=(nullptr_t, const unique_ptr<T, D>& y);
  // class bad_weak_ptr
  class bad_weak_ptr;
  // class template shared_ptr
  template<class T> class shared_ptr;
  // 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);
  // shared_ptr comparisons
  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>& x, nullptr_t) noexcept;
  template <class T>
  bool operator==(nullptr_t, const shared_ptr<T>& y) noexcept;
  template <class T>
  bool operator!=(const shared_ptr<T>& x, nullptr_t) noexcept;
  template <class T>
  bool operator!=(nullptr_t, const shared_ptr<T>& y) noexcept;
  template <class T>
  bool operator<(const shared_ptr<T>& x, nullptr_t) noexcept;
  template <class T>
  bool operator<(nullptr_t, const shared_ptr<T>& y) noexcept;
  template <class T>
  bool operator<=(const shared_ptr<T>& x, nullptr_t) noexcept;
  template <class T>
  bool operator<=(nullptr_t, const shared_ptr<T>& y) noexcept;
  template <class T>
  bool operator>(const shared_ptr<T>& x, nullptr_t) noexcept;
  template <class T>
  bool operator>(nullptr_t, const shared_ptr<T>& y) noexcept;
  template <class T>
  bool operator>=(const shared_ptr<T>& x, nullptr_t) noexcept;
  template <class T>
  bool operator>=(nullptr_t, const shared_ptr<T>& y) noexcept;
  // shared_ptr specialized algorithms
  template<class T> void swap(shared_ptr<T>& a, shared_ptr<T>& b) noexcept;
  // 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;
  // shared_ptr get_deleter
  template<class D, class T> D* get_deleter(const shared_ptr<T>& p) noexcept;
  // 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);
  // class template weak_ptr
  template<class T> class weak_ptr;
  // weak_ptr specialized algorithms
  template<class T> void swap(weak_ptr<T>& a, weak_ptr<T>& b) noexcept;
  // class template owner_less
  template<class T = void> struct owner_less;
  // class template enable_shared_from_this
  template<class T> class enable_shared_from_this;
  // 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);
  // hash support
  template <class T> struct hash;
  template <class T, class D> struct hash<unique_ptr<T, D>>;
  template <class T> struct hash<shared_ptr<T>>;
  // uses_allocator
  template <class T, class Alloc>
  constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value;
}

Class template std::pointer_traits

namespace std {
  template <class Ptr> struct pointer_traits {
    using pointer = Ptr;
    using element_type = /*see definition*/ ;
    using difference_type = /*see definition*/ ;
    template <class U> using rebind = /*see definition*/ ;
    static pointer pointer_to(/*see definition*/ r);
  };
  template <class T> struct pointer_traits<T*> {
    using pointer = T*;
    using element_type = T;
    using difference_type = ptrdiff_t;
    template <class U> using rebind = U*;
    static pointer pointer_to(/*see definition*/ r) noexcept;
  };
}

Class template std::allocator_traits

namespace std {
  template <class Alloc> struct allocator_traits {
    using allocator_type = Alloc;
    using value_type = typename Alloc::value_type;
    using pointer = /*see definition*/ ;
    using const_pointer = /*see definition*/ ;
    using void_pointer = /*see definition*/ ;
    using const_void_pointer = /*see definition*/ ;
    using difference_type = /*see definition*/ ;
    using size_type = /*see definition*/ ;
    using propagate_on_container_copy_assignment = /*see definition*/ ;
    using propagate_on_container_move_assignment = /*see definition*/ ;
    using propagate_on_container_swap = /*see definition*/ ;
    using is_always_equal = /*see definition*/ ;
    template <class T> using rebind_alloc = /*see definition*/ ;
    template <class T> using rebind_traits = allocator_traits<rebind_alloc<T>>;
    static pointer allocate(Alloc& a, size_type n);
    static pointer allocate(Alloc& a, size_type n, const_void_pointer hint);
    static void deallocate(Alloc& a, pointer p, size_type n);
    template <class T, class... Args>
    static void construct(Alloc& a, T* p, Args&&... args);
    template <class T>
    static void destroy(Alloc& a, T* p);
    static size_type max_size(const Alloc& a) noexcept;
    static Alloc select_on_container_copy_construction(const Alloc& rhs);
  };
}

Class template std::allocator

namespace std {
  template <class T> class allocator {
  public:
    using value_type = T;
    using propagate_on_container_move_assignment = true_type;
    using is_always_equal = true_type;
    allocator() noexcept;
    allocator(const allocator&) noexcept;
    template <class U> allocator(const allocator<U>&) noexcept;
    ~allocator();
    T* allocate(size_t n);
    void deallocate(T* p, size_t n);
  };
}

Class template std::default_delete

namespace std {
  template <class T>
  struct default_delete {
    constexpr default_delete() noexcept = default;
    template <class U> default_delete(const default_delete<U>&) noexcept;
    void operator()(T*) const;
  };
  template <class T>
  struct default_delete<T[]> {
    constexpr default_delete() noexcept = default;
    template <class U> default_delete(const default_delete<U[]>&) noexcept;
    template <class U> void operator()(U* ptr) const;
  };
}

Class template std::unique_ptr

namespace std {
  template <class T, class D = default_delete<T>>
  class unique_ptr {
  public:
    using pointer = /*see definition*/ ;
    using element_type = T;
    using deleter_type = D;
    // constructors
    constexpr unique_ptr() noexcept;
    explicit unique_ptr(pointer p) noexcept;
    unique_ptr(pointer p, /*see definition*/ d1) noexcept;
    unique_ptr(pointer p, /*see definition*/ d2) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
    template <class U, class E>
    unique_ptr(unique_ptr<U, E>&& u) noexcept;
    // destructor
    ~unique_ptr();
    // assignment
    unique_ptr& operator=(unique_ptr&& u) noexcept;
    template <class U, class E> unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    unique_ptr& operator=(nullptr_t) noexcept;
    // observers
    add_lvalue_reference_t<T> operator*() const;
    pointer operator->() const noexcept;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;
    // modifiers
    pointer release() noexcept;
    void reset(pointer p = pointer()) noexcept;
    void swap(unique_ptr& u) noexcept;
    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
 
  template <class T, class D>
  class unique_ptr<T[], D> {
  public:
    using pointer = /*see definition*/ ;
    using element_type = T;
    using deleter_type = D;
    // constructors
    constexpr unique_ptr() noexcept;
    template <class U> explicit unique_ptr(U p) noexcept;
    template <class U> unique_ptr(U p, /*see definition*/d) noexcept;
    template <class U> unique_ptr(U p, /*see definition*/d) noexcept;
    unique_ptr(unique_ptr&& u) noexcept;
    template <class U, class E>
    unique_ptr(unique_ptr<U, E>&& u) noexcept;
    constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() { }
    // destructor
    ~unique_ptr();
    // assignment
    unique_ptr& operator=(unique_ptr&& u) noexcept;
    template <class U, class E>
    unique_ptr& operator=(unique_ptr<U, E>&& u) noexcept;
    unique_ptr& operator=(nullptr_t) noexcept;
    // observers
    T& operator[](size_t i) const;
    pointer get() const noexcept;
    deleter_type& get_deleter() noexcept;
    const deleter_type& get_deleter() const noexcept;
    explicit operator bool() const noexcept;
    // modifiers
    pointer release() noexcept;
    template <class U> void reset(U p) noexcept;
    void reset(nullptr_t = nullptr) noexcept;
    void swap(unique_ptr& u) noexcept;
    // disable copy from lvalue
    unique_ptr(const unique_ptr&) = delete;
    unique_ptr& operator=(const unique_ptr&) = delete;
  };
}

Class std::bad_weak_ptr

namespace std {
  class bad_weak_ptr : public exception {
  public:
    bad_weak_ptr() noexcept;
  };
}

Class template std::shared_ptr

namespace std {
  template<class T>
  class shared_ptr {
  public:
    using element_type = remove_extent_t<T>;
    using weak_type = weak_ptr<T>;
    // 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, class D> shared_ptr(unique_ptr<Y, D>&& r);
    constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { }
    // destructor
    ~shared_ptr();
    // assignment
    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, class D> shared_ptr& operator=(unique_ptr<Y, D>&& r);
    // modifiers
    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);
    // observers
    element_type* get() const noexcept;
    T& operator*() const noexcept;
    T* operator->() const noexcept;
    element_type& operator[](ptrdiff_t i) const;
    long use_count() const noexcept;
    explicit operator bool() const noexcept;
    template<class U> bool owner_before(const shared_ptr<U>& b) const;
    template<class U> bool owner_before(const weak_ptr<U>& b) const;
  };
}

Class template std::weak_ptr

namespace std {
  template<class T>
  class weak_ptr {
  public:
    using element_type = T;
    // constructors
    constexpr weak_ptr() noexcept;
    template<class Y> weak_ptr(const shared_ptr<Y>& r) noexcept;
    weak_ptr(const weak_ptr& r) noexcept;
    template<class Y> weak_ptr(const weak_ptr<Y>& r) noexcept;
    weak_ptr(weak_ptr&& r) noexcept;
    template<class Y> weak_ptr(weak_ptr<Y>&& r) noexcept;
    // destructor
    ~weak_ptr();
    // assignment
    weak_ptr& operator=(const weak_ptr& r) noexcept;
    template<class Y> weak_ptr& operator=(const weak_ptr<Y>& r) noexcept;
    template<class Y> weak_ptr& operator=(const shared_ptr<Y>& r) noexcept;
    weak_ptr& operator=(weak_ptr&& r) noexcept;
    template<class Y> weak_ptr& operator=(weak_ptr<Y>&& r) noexcept;
    // modifiers
    void swap(weak_ptr& r) noexcept;
    void reset() noexcept;
    // observers
    long use_count() const noexcept;
    bool expired() const noexcept;
    shared_ptr<T> lock() const noexcept;
    template<class U> bool owner_before(const shared_ptr<U>& b) const;
    template<class U> bool owner_before(const weak_ptr<U>& b) const;
  };
}

Class template std::owner_less

namespace std {
  template<class T = void> struct owner_less;
  template<class T> struct owner_less<shared_ptr<T>> {
    bool operator()(const shared_ptr<T>&, const shared_ptr<T>&) const;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const;
  };
  template<class T> struct owner_less<weak_ptr<T>> {
    bool operator()(const weak_ptr<T>&, const weak_ptr<T>&) const;
    bool operator()(const shared_ptr<T>&, const weak_ptr<T>&) const;
    bool operator()(const weak_ptr<T>&, const shared_ptr<T>&) const;
  };
  template<> struct owner_less<void> {
    template<class T, class U>
    bool operator()(const shared_ptr<T>&, const shared_ptr<U>&) const;
    template<class T, class U>
    bool operator()(const shared_ptr<T>&, const weak_ptr<U>&) const;
    template<class T, class U>
    bool operator()(const weak_ptr<T>&, const shared_ptr<U>&) const;
    template<class T, class U>
    bool operator()(const weak_ptr<T>&, const weak_ptr<U>&) const;
    using is_transparent = /*unspecified*/ ;
  };
}

Class template std::enable_shared_from_this

namespace std {
  template<class T> class enable_shared_from_this {
  protected:
    constexpr enable_shared_from_this() noexcept;
    enable_shared_from_this(const enable_shared_from_this&) noexcept;
    enable_shared_from_this& operator=(const enable_shared_from_this&) noexcept;
    ~enable_shared_from_this();
  public:
    shared_ptr<T> shared_from_this();
    shared_ptr<T const> shared_from_this() const;
    weak_ptr<T> weak_from_this() noexcept;
    weak_ptr<T const> weak_from_this() const noexcept;
  private:
    mutable weak_ptr<T> weak_this; // exposition only
  };
}