Memory

Header <experimental/memory> synopsis

#include <memory>

namespace std {
  namespace experimental::inline fundamentals_v3 {

    
    template <class W> class observer_ptr;

    
    template <class W>
    void swap(observer_ptr<W>&, observer_ptr<W>&) noexcept;
    template <class W>
    observer_ptr<W> make_observer(W*) noexcept;
    // (in)equality operators
    template <class W1, class W2>
    bool operator==(observer_ptr<W1>, observer_ptr<W2>);

    template <class W1, class W2>
    bool operator!=(observer_ptr<W1>, observer_ptr<W2>);
    template <class W>
    bool operator==(observer_ptr<W>, nullptr_t) noexcept;
    template <class W>
    bool operator!=(observer_ptr<W>, nullptr_t) noexcept;
    template <class W>
    bool operator==(nullptr_t, observer_ptr<W>) noexcept;
    template <class W>
    bool operator!=(nullptr_t, observer_ptr<W>) noexcept;
    // ordering operators
    template <class W1, class W2>
    bool operator<(observer_ptr<W1>, observer_ptr<W2>);
    template <class W1, class W2>
    bool operator>(observer_ptr<W1>, observer_ptr<W2>);
    template <class W1, class W2>
    bool operator<=(observer_ptr<W1>, observer_ptr<W2>);
    template <class W1, class W2>
    bool operator>=(observer_ptr<W1>, observer_ptr<W2>);

  } // namespace experimental::inline fundamentals_v3

  
  template <class T> struct hash;
  template <class T> struct hash<experimental::observer_ptr<T>>;

} // namespace std

Non-owning (observer) pointers

Class template observer_ptr overview

namespace std::experimental::inline fundamentals_v3 {

  template <class W> class observer_ptr {
    using pointer = add_pointer_t<W>;            // exposition-only
    using reference = add_lvalue_reference_t<W>; // exposition-only
  public:
    // publish our template parameter and variations thereof
    using element_type = W;

    
    // default constructor
    constexpr observer_ptr() noexcept;

    // pointer-accepting constructors
    constexpr observer_ptr(nullptr_t) noexcept;
    constexpr explicit observer_ptr(pointer) noexcept;

    // copying constructors (in addition to the implicit copy constructor)
    template <class W2> constexpr observer_ptr(observer_ptr<W2>) noexcept;

    
    constexpr pointer get() const noexcept;
    constexpr reference operator*() const;
    constexpr pointer operator->() const noexcept;
    constexpr explicit operator bool() const noexcept;

    
    constexpr explicit operator pointer() const noexcept;

    
    constexpr pointer release() noexcept;
    constexpr void reset(pointer = nullptr) noexcept;
    constexpr void swap(observer_ptr&) noexcept;
  }; // observer_ptr<>

} // namespace std::experimental::inline fundamentals_v3

A non-owning pointer, known as an observer, is an object o that stores a pointer to a second object, w. In this context, w is known as a watched object. There is no watched object when the stored pointer is nullptr. An observer takes no responsibility or ownership of any kind for its watched object, if any; in particular, there is no inherent relationship between the lifetimes of o and w.

Specializations of observer_ptr shall meet the requirements of a Cpp17CopyConstructible and Cpp17CopyAssignable type. The template parameter W of an observer_ptr shall not be a reference type, but may be an incomplete type.

The uses of observer_ptr include clarity of interface specification in new code, and interoperability with pointer-based legacy code.

observer_ptr constructors

constexpr observer_ptr() noexcept; constexpr observer_ptr(nullptr_t) noexcept; Constructs an observer_ptr object that has no corresponding watched object. get() == nullptr. constexpr explicit observer_ptr(pointer other) noexcept; get() == other. template <class W2> constexpr observer_ptr(observer_ptr<W2> other) noexcept; W2* is convertible to W*. get() == other.get().

observer_ptr observers

constexpr pointer get() const noexcept; The stored pointer. constexpr reference operator*() const; get() != nullptr is true. *get(). Nothing. constexpr pointer operator->() const noexcept; get(). constexpr explicit operator bool() const noexcept; get() != nullptr.

observer_ptr conversions

constexpr explicit operator pointer() const noexcept; get().

observer_ptr modifiers

constexpr pointer release() noexcept; get() == nullptr. The value get() had at the start of the call to release. constexpr void reset(pointer p = nullptr) noexcept; get() == p. constexpr void swap(observer_ptr& other) noexcept; Invokes swap on the stored pointers of *this and other.

observer_ptr specialized algorithms

template <class W> void swap(observer_ptr<W>& p1, observer_ptr<W>& p2) noexcept; p1.swap(p2). template <class W> observer_ptr<W> make_observer(W* p) noexcept; observer_ptr<W>{p}. template <class W1, class W2> bool operator==(observer_ptr<W1> p1, observer_ptr<W2> p2); p1.get() == p2.get(). template <class W1, class W2> bool operator!=(observer_ptr<W1> p1, observer_ptr<W2> p2); not (p1 == p2). template <class W> bool operator==(observer_ptr<W> p, nullptr_t) noexcept; template <class W> bool operator==(nullptr_t, observer_ptr<W> p) noexcept; not p. template <class W> bool operator!=(observer_ptr<W> p, nullptr_t) noexcept; template <class W> bool operator!=(nullptr_t, observer_ptr<W> p) noexcept; (bool)p. template <class W1, class W2> bool operator<(observer_ptr<W1> p1, observer_ptr<W2> p2); less<W3>()(p1.get(), p2.get()), where W3 is the composite pointer type () of W1* and W2*. template <class W1, class W2> bool operator>(observer_ptr<W1> p1, observer_ptr<W2> p2); p2 < p1. template <class W1, class W2> bool operator<=(observer_ptr<W1> p1, observer_ptr<W2> p2); not (p2 < p1). template <class W1, class W2> bool operator>=(observer_ptr<W1> p1, observer_ptr<W2> p2); not (p1 < p2).

observer_ptr hash support

template <class T> struct hash<experimental::observer_ptr<T>>;

The specialization is enabled (). For an object p of type observer_ptr<T>, hash<observer_ptr<T>>()(p) evaluates to the same value as hash<T*>()(p.get()).

Header <experimental/memory_resource> synopsis

namespace std::pmr::experimental::inline fundamentals_v3 {

  // The name resource_adaptor_imp is for exposition only.
  template <class Allocator> class resource_adaptor_imp;

  template <class Allocator>
    using resource_adaptor = resource_adaptor_imp<
      typename allocator_traits<Allocator>::template rebind_alloc<char>>;

} // namespace std::pmr::experimental::inline fundamentals_v3

Alias template resource_adaptor

resource_adaptor

An instance of resource_adaptor<Allocator> is an adaptor that wraps a memory_resource interface around Allocator. In order that resource_adaptor<X<T>> and resource_adaptor<X<U>> are the same type for any allocator template X and types T and U, resource_adaptor<Allocator> is rendered as an alias to a class template such that Allocator is rebound to a char value type in every specialization of the class template. The requirements on this class template are defined below. The name resource_adaptor_imp is for exposition only and is not normative, but the definitions of the members of that class, whatever its name, are normative. In addition to the Cpp17Allocator requirements (), the parameter to resource_adaptor shall meet the following additional requirements:

  • typename allocator_traits<Allocator>::pointer shall be identical to typename allocator_traits<Allocator>::value_type*.
  • typename allocator_traits<Allocator>::const_pointer shall be identical to typename allocator_traits<Allocator>::value_type const*.
  • typename allocator_traits<Allocator>::void_pointer shall be identical to void*.
  • typename allocator_traits<Allocator>::const_void_pointer shall be identical to void const*.

// The name resource_adaptor_imp is for exposition only.
template <class Allocator>
class resource_adaptor_imp : public memory_resource {
  // for exposition only
  Allocator m_alloc;

public:
  using allocator_type = Allocator;

  resource_adaptor_imp() = default;
  resource_adaptor_imp(const resource_adaptor_imp&) = default;
  resource_adaptor_imp(resource_adaptor_imp&&) = default;

  explicit resource_adaptor_imp(const Allocator& a2);
  explicit resource_adaptor_imp(Allocator&& a2);

  resource_adaptor_imp& operator=(const resource_adaptor_imp&) = default;

  allocator_type get_allocator() const { return m_alloc; }

protected:
  virtual void* do_allocate(size_t bytes, size_t alignment);
  virtual void do_deallocate(void* p, size_t bytes, size_t alignment);

  virtual bool do_is_equal(const memory_resource& other) const noexcept;
};

template <class Allocator>
  using resource_adaptor = typename resource_adaptor_imp<
    typename allocator_traits<Allocator>::template rebind_alloc<char>>;

resource_adaptor_imp constructors

explicit resource_adaptor_imp(const Allocator& a2); Initializes m_alloc with a2. explicit resource_adaptor_imp(Allocator&& a2); Initializes m_alloc with std::move(a2).

resource_adaptor_imp member functions

void* do_allocate(size_t bytes, size_t alignment); Allocated memory obtained by calling m_alloc.allocate. The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource (). void do_deallocate(void* p, size_t bytes, size_t alignment); p was previously allocated using A.allocate, where A == m_alloc, and not subsequently deallocated. Returns memory to the allocator using m_alloc.deallocate(). bool do_is_equal(const memory_resource& other) const noexcept;

Let p be dynamic_cast<const resource_adaptor_imp*>(&other).

false if p is null, otherwise the value of m_alloc == p->m_alloc.