[indirect]

# 20 Memory management library [[mem]](./#mem)

## 20.4 Types for composite class design [[mem.composite.types]](mem.composite.types#indirect)

### 20.4.1 Class template indirect [indirect]

#### [20.4.1.1](#general) General [[indirect.general]](indirect.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5901)

An indirect object manages the lifetime of an owned object[.](#general-1.sentence-1)

An indirect object is[*valueless*](#def:valueless,indirect_object "20.4.1.1 General [indirect.general]") if it has no owned object[.](#general-1.sentence-2)

An indirect object may become valueless only after it has been moved from[.](#general-1.sentence-3)

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5907)

In every specialization indirect<T, Allocator>,
if the type allocator_traits<Allocator>​::​value_type is not the same type as T,
the program is ill-formed[.](#general-2.sentence-1)

Every object of type indirect<T, Allocator> uses an object of type Allocator to allocate and free storage
for the owned object as needed[.](#general-2.sentence-2)

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5916)

Constructing an owned object with args... using the allocator a means callingallocator_traits<Allocator>​::​construct(a, *p*, args...) whereargs is an expression pack,a is an allocator, and*p* is a pointer obtained by
calling allocator_traits<Allocator>​::​allocate[.](#general-3.sentence-1)

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5925)

The member *alloc* is used for
any memory allocation and element construction
performed by member functions
during the lifetime of each indirect object[.](#general-4.sentence-1)

The allocator *alloc* may be replaced
only via assignment or swap()[.](#general-4.sentence-2)

Allocator replacement is performed by
copy assignment,
move assignment, or
swapping of the allocator
only if ([[container.reqmts]](container.reqmts "23.2.2.2 Container requirements")):

- [(4.1)](#general-4.1)

allocator_traits<Allocator>​::​propagate_on_container_copy_assignment​::​value, or

- [(4.2)](#general-4.2)

allocator_traits<Allocator>​::​propagate_on_container_move_assignment​::​value, or

- [(4.3)](#general-4.3)

allocator_traits<Allocator>​::​propagate_on_container_swap​::​value

is true within the implementation of
the corresponding indirect operation[.](#general-4.sentence-3)

[5](#general-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5948)

A program that instantiates the definition of
the template indirect<T, Allocator> with
a type for the T parameter that is
a non-object type,
an array type,in_place_t,
a specialization of in_place_type_t, or
a cv-qualified type
is ill-formed[.](#general-5.sentence-1)

[6](#general-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5959)

The template parameter T of indirect may be an incomplete type[.](#general-6.sentence-1)

[7](#general-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5963)

The template parameter Allocator of indirect shall meet the *Cpp17Allocator* requirements[.](#general-7.sentence-1)

[8](#general-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L5967)

If a program declares an explicit or partial specialization of indirect,
the behavior is undefined[.](#general-8.sentence-1)

#### [20.4.1.2](#syn) Synopsis [[indirect.syn]](indirect.syn)

[ð](#lib:indirect)

namespace std {template<class T, class Allocator = allocator<T>>class indirect {public:using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits<Allocator>::pointer; using const_pointer = typename allocator_traits<Allocator>::const_pointer; // [[indirect.ctor]](#ctor "20.4.1.3 Constructors"), constructorsconstexpr explicit indirect(); constexpr explicit indirect(allocator_arg_t, const Allocator& a); constexpr indirect(const indirect& other); constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other); constexpr indirect(indirect&& other) noexcept; constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)noexcept(*see below*); template<class U = T>constexpr explicit indirect(U&& u); template<class U = T>constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u); template<class... Us>constexpr explicit indirect(in_place_t, Us&&... us); template<class... Us>constexpr explicit indirect(allocator_arg_t, const Allocator& a,
 in_place_t, Us&&... us); template<class I, class... Us>constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us); template<class I, class... Us>constexpr explicit indirect(allocator_arg_t, const Allocator& a,
 in_place_t, initializer_list<I> ilist, Us&&... us); // [[indirect.dtor]](#dtor "20.4.1.4 Destructor"), destructorconstexpr ~indirect(); // [[indirect.assign]](#assign "20.4.1.5 Assignment"), assignmentconstexpr indirect& operator=(const indirect& other); constexpr indirect& operator=(indirect&& other) noexcept(*see below*); template<class U = T>constexpr indirect& operator=(U&& u); // [[indirect.obs]](#obs "20.4.1.6 Observers"), observersconstexpr const T& operator*() const & noexcept; constexpr T& operator*() & noexcept; constexpr const T&& operator*() const && noexcept; constexpr T&& operator*() && noexcept; constexpr const_pointer operator->() const noexcept; constexpr pointer operator->() noexcept; constexpr bool valueless_after_move() const noexcept; constexpr allocator_type get_allocator() const noexcept; // [[indirect.swap]](#swap "20.4.1.7 Swap"), swapconstexpr void swap(indirect& other) noexcept(*see below*); friend constexpr void swap(indirect& lhs, indirect& rhs) noexcept(*see below*); // [[indirect.relops]](#relops "20.4.1.8 Relational operators"), relational operatorstemplate<class U, class AA>friend constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)noexcept(*see below*); template<class U, class AA>friend constexpr auto operator<=>(const indirect& lhs, const indirect<U, AA>& rhs)-> *synth-three-way-result*<T, U>; // [[indirect.comp.with.t]](#comp.with.t "20.4.1.9 Comparison with T"), comparison with Ttemplate<class U>friend constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(*see below*); template<class U>friend constexpr auto operator<=>(const indirect& lhs, const U& rhs)-> *synth-three-way-result*<T, U>; private: pointer *p*; // *exposition only* Allocator *alloc* = Allocator(); // *exposition only*}; template<class Value> indirect(Value) -> indirect<Value>; template<class Allocator, class Value> indirect(allocator_arg_t, Allocator, Value)-> indirect<Value, typename allocator_traits<Allocator>::template rebind_alloc<Value>>;}

#### [20.4.1.3](#ctor) Constructors [[indirect.ctor]](indirect.ctor)

[1](#ctor-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6059)

The following element applies to all functions in [[indirect.ctor]](#ctor "20.4.1.3 Constructors"):

[2](#ctor-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6063)

*Throws*: Nothing unless allocator_traits<Allocator>​::​allocate orallocator_traits<Allocator>​::​construct throws[.](#ctor-2.sentence-1)

[ð](#lib:indirect,constructor)

`constexpr explicit indirect();
`

[3](#ctor-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6075)

*Constraints*: is_default_constructible_v<Allocator> is true[.](#ctor-3.sentence-1)

[4](#ctor-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6079)

*Mandates*: is_default_constructible_v<T> is true[.](#ctor-4.sentence-1)

[5](#ctor-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6083)

*Effects*: Constructs an owned object of type T with an empty argument list,
using the allocator *alloc*[.](#ctor-5.sentence-1)

[ð](#lib:indirect,constructor_)

`constexpr explicit indirect(allocator_arg_t, const Allocator& a);
`

[6](#ctor-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6095)

*Mandates*: is_default_constructible_v<T> is true[.](#ctor-6.sentence-1)

[7](#ctor-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6099)

*Effects*: *alloc* is direct-non-list-initialized with a[.](#ctor-7.sentence-1)

Constructs an owned object of type T with an empty argument list,
using the allocator *alloc*[.](#ctor-7.sentence-2)

[ð](#lib:indirect,constructor__)

`constexpr indirect(const indirect& other);
`

[8](#ctor-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6112)

*Mandates*: is_copy_constructible_v<T> is true[.](#ctor-8.sentence-1)

[9](#ctor-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6116)

*Effects*: *alloc* is direct-non-list-initialized withallocator_traits<Allocator>​::​select_on_container_copy_construction(other.*alloc*)[.](#ctor-9.sentence-1)

If other is valueless, *this is valueless[.](#ctor-9.sentence-2)

Otherwise,
constructs an owned object of type T with *other,
using the allocator *alloc*[.](#ctor-9.sentence-3)

[ð](#lib:indirect,constructor___)

`constexpr indirect(allocator_arg_t, const Allocator& a, const indirect& other);
`

[10](#ctor-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6132)

*Mandates*: is_copy_constructible_v<T> is true[.](#ctor-10.sentence-1)

[11](#ctor-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6136)

*Effects*: *alloc* is direct-non-list-initialized with a[.](#ctor-11.sentence-1)

If other is valueless, *this is valueless[.](#ctor-11.sentence-2)

Otherwise,
constructs an owned object of type T with *other,
using the allocator *alloc*[.](#ctor-11.sentence-3)

[ð](#lib:indirect,constructor____)

`constexpr indirect(indirect&& other) noexcept;
`

[12](#ctor-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6151)

*Effects*: *alloc* is direct-non-list-initialized fromstd​::​move(other.*alloc*)[.](#ctor-12.sentence-1)

If other is valueless, *this is valueless[.](#ctor-12.sentence-2)

Otherwise *this takes ownership of the owned object of other[.](#ctor-12.sentence-3)

[13](#ctor-13)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6158)

*Postconditions*: other is valueless[.](#ctor-13.sentence-1)

[ð](#lib:indirect,constructor_____)

`constexpr indirect(allocator_arg_t, const Allocator& a, indirect&& other)
  noexcept(allocator_traits<Allocator>::is_always_equal::value);
`

[14](#ctor-14)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6170)

*Mandates*: If allocator_traits<Allocator>​::​is_always_equal​::​value is false then T is a complete type[.](#ctor-14.sentence-1)

[15](#ctor-15)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6175)

*Effects*: *alloc* is direct-non-list-initialized with a[.](#ctor-15.sentence-1)

If other is valueless, *this is valueless[.](#ctor-15.sentence-2)

Otherwise,
if *alloc* == other.*alloc* is true,
constructs an object of type indirect that
takes ownership of the owned object of other[.](#ctor-15.sentence-3)

Otherwise,
constructs an owned object of type T with *std​::​move(other),
using the allocator *alloc*[.](#ctor-15.sentence-4)

[16](#ctor-16)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6187)

*Postconditions*: other is valueless[.](#ctor-16.sentence-1)

[ð](#lib:indirect,constructor______)

`template<class U = T>
  constexpr explicit indirect(U&& u);
`

[17](#ctor-17)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6199)

*Constraints*: 

- [(17.1)](#ctor-17.1)

is_same_v<remove_cvref_t<U>, indirect> is false,

- [(17.2)](#ctor-17.2)

is_same_v<remove_cvref_t<U>, in_place_t> is false,

- [(17.3)](#ctor-17.3)

is_constructible_v<T, U> is true, and

- [(17.4)](#ctor-17.4)

is_default_constructible_v<Allocator> is true[.](#ctor-17.sentence-1)

[18](#ctor-18)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6212)

*Effects*: Constructs an owned object of type T with std​::​forward<U>(u),
using the allocator *alloc*[.](#ctor-18.sentence-1)

[ð](#lib:indirect,constructor_______)

`template<class U = T>
  constexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u);
`

[19](#ctor-19)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6225)

*Constraints*: 

- [(19.1)](#ctor-19.1)

is_same_v<remove_cvref_t<U>, indirect> is false,

- [(19.2)](#ctor-19.2)

is_same_v<remove_cvref_t<U>, in_place_t> is false, and

- [(19.3)](#ctor-19.3)

is_constructible_v<T, U> is true[.](#ctor-19.sentence-1)

[20](#ctor-20)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6236)

*Effects*: *alloc* is direct-non-list-initialized with a[.](#ctor-20.sentence-1)

Constructs an owned object of type T withstd​::​forward<U>(u),
using the allocator *alloc*[.](#ctor-20.sentence-2)

[ð](#lib:indirect,constructor________)

`template<class... Us>
  constexpr explicit indirect(in_place_t, Us&&... us);
`

[21](#ctor-21)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6251)

*Constraints*: 

- [(21.1)](#ctor-21.1)

is_constructible_v<T, Us...> is true, and

- [(21.2)](#ctor-21.2)

is_default_constructible_v<Allocator> is true[.](#ctor-21.sentence-1)

[22](#ctor-22)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6260)

*Effects*: Constructs an owned object of type T withstd​::​forward<Us>(us)...,
using the allocator *alloc*[.](#ctor-22.sentence-1)

[ð](#lib:indirect,constructor_________)

`template<class... Us>
  constexpr explicit indirect(allocator_arg_t, const Allocator& a,
                              in_place_t, Us&& ...us);
`

[23](#ctor-23)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6275)

*Constraints*: is_constructible_v<T, Us...> is true[.](#ctor-23.sentence-1)

[24](#ctor-24)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6279)

*Effects*: *alloc* is direct-non-list-initialized with a[.](#ctor-24.sentence-1)

Constructs an owned object of type T withstd​::​forward<Us>(us)...,
using the allocator *alloc*[.](#ctor-24.sentence-2)

[ð](#lib:indirect,constructor__________)

`template<class I, class... Us>
  constexpr explicit indirect(in_place_t, initializer_list<I> ilist, Us&&... us);
`

[25](#ctor-25)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6294)

*Constraints*: 

- [(25.1)](#ctor-25.1)

is_constructible_v<T, initializer_list<I>&, Us...> is true, and

- [(25.2)](#ctor-25.2)

is_default_constructible_v<Allocator> is true[.](#ctor-25.sentence-1)

[26](#ctor-26)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6303)

*Effects*: Constructs an owned object of type T with the argumentsilist, std​::​forward<Us>(us)...,
using the allocator *alloc*[.](#ctor-26.sentence-1)

[ð](#lib:indirect,constructor___________)

`template<class I, class... Us>
  constexpr explicit indirect(allocator_arg_t, const Allocator& a,
                              in_place_t, initializer_list<I> ilist, Us&&... us);
`

[27](#ctor-27)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6318)

*Constraints*: is_constructible_v<T, initializer_list<I>&, Us...> is true[.](#ctor-27.sentence-1)

[28](#ctor-28)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6322)

*Effects*: *alloc* is direct-non-list-initialized with a[.](#ctor-28.sentence-1)

Constructs an owned object of type T with the argumentsilist, std​::​forward<Us>(us)...,
using the allocator *alloc*[.](#ctor-28.sentence-2)

#### [20.4.1.4](#dtor) Destructor [[indirect.dtor]](indirect.dtor)

[ð](#lib:indirect,destructor)

`constexpr ~indirect();
`

[1](#dtor-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6338)

*Mandates*: T is a complete type[.](#dtor-1.sentence-1)

[2](#dtor-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6342)

*Effects*: If *this is not valueless,
destroys the owned object
using allocator_traits<Allocator>​::​destroy and
then the storage is deallocated[.](#dtor-2.sentence-1)

#### [20.4.1.5](#assign) Assignment [[indirect.assign]](indirect.assign)

[ð](#lib:operator=,indirect)

`constexpr indirect& operator=(const indirect& other);
`

[1](#assign-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6358)

*Mandates*: 

- [(1.1)](#assign-1.1)

is_copy_assignable_v<T> is true, and

- [(1.2)](#assign-1.2)

is_copy_constructible_v<T> is true[.](#assign-1.sentence-1)

[2](#assign-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6368)

*Effects*: If addressof(other) == this is true, there are no effects[.](#assign-2.sentence-1)

Otherwise:

- [(2.1)](#assign-2.1)

  The allocator needs updating ifallocator_traits<Allocator>​::​propagate_on_container_copy_assignment​::​value is true[.](#assign-2.1.sentence-1)

- [(2.2)](#assign-2.2)

  If other is valueless,*this becomes valueless and
the owned object in *this, if any,
is destroyed using allocator_traits<Allocator>​::​destroy and
then the storage is deallocated[.](#assign-2.2.sentence-1)

- [(2.3)](#assign-2.3)

  Otherwise,
if *alloc* == other.*alloc* is true and*this is not valueless,
equivalent to **this = *other[.](#assign-2.3.sentence-1)

- [(2.4)](#assign-2.4)

  Otherwise a new owned object is constructed in *this using allocator_traits<Allocator>​::​con  
struct with
the owned object from other as the argument,
using either the allocator in *this or
the allocator in other if the allocator needs updating[.](#assign-2.4.sentence-1)

- [(2.5)](#assign-2.5)

  The previously owned object in *this, if any,
is destroyed using allocator_traits<Allocator>​::​  
destroy and
then the storage is deallocated[.](#assign-2.5.sentence-1)

- [(2.6)](#assign-2.6)

  If the allocator needs updating,
the allocator in *this is replaced with
a copy of the allocator in other[.](#assign-2.6.sentence-1)

[3](#assign-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6415)

*Returns*: A reference to *this[.](#assign-3.sentence-1)

[4](#assign-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6419)

*Remarks*: If any exception is thrown,
the result of the expression this->valueless_after_move() remains unchanged[.](#assign-4.sentence-1)

If an exception is thrown during
the call to T's selected copy constructor, no effect[.](#assign-4.sentence-2)

If an exception is thrown during the call to T's copy assignment,
the state of its owned object
is as defined by the exception safety guarantee ofT's copy assignment[.](#assign-4.sentence-3)

[ð](#lib:operator=,indirect_)

`constexpr indirect& operator=(indirect&& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_move_assignment::value ||
           allocator_traits<Allocator>::is_always_equal::value);
`

[5](#assign-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6440)

*Mandates*: is_copy_constructible_t<T> is true[.](#assign-5.sentence-1)

[6](#assign-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6444)

*Effects*: If addressof(other) == this is true, there are no effects[.](#assign-6.sentence-1)

Otherwise:

- [(6.1)](#assign-6.1)

  The allocator needs updating ifallocator_traits<Allocator>​::​propagate_on_container_move_assignment​::​value is true[.](#assign-6.1.sentence-1)

- [(6.2)](#assign-6.2)

  If other is valueless,*this becomes valueless and
the owned object in *this, if any,
is destroyed using allocator_traits<Allocator>​::​destroy and
then the storage is deallocated[.](#assign-6.2.sentence-1)

- [(6.3)](#assign-6.3)

  Otherwise,
if *alloc* == other.*alloc* is true,
swaps the owned objects in *this and other;
the owned object in other, if any,
is then destroyed using allocator_traits<Allocator>​::​destroy and
then the storage is deallocated[.](#assign-6.3.sentence-1)

- [(6.4)](#assign-6.4)

  Otherwise,
constructs a new owned object with
the owned object of other as the argument as an rvalue,
using either
the allocator in *this or
the allocator in other if the allocator needs updating[.](#assign-6.4.sentence-1)

- [(6.5)](#assign-6.5)

  The previously owned object in *this, if any,
is destroyed using allocator_traits<Allocator>​::​  
destroy and
then the storage is deallocated[.](#assign-6.5.sentence-1)

- [(6.6)](#assign-6.6)

  If the allocator needs updating,
the allocator in *this is replaced with
a copy of the allocator in other[.](#assign-6.6.sentence-1)

[7](#assign-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6493)

*Postconditions*: other is valueless[.](#assign-7.sentence-1)

[8](#assign-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6497)

*Returns*: A reference to *this[.](#assign-8.sentence-1)

[9](#assign-9)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6501)

*Remarks*: If any exception is thrown,
there are no effects on *this or other[.](#assign-9.sentence-1)

[ð](#lib:operator=,indirect__)

`template<class U = T>
  constexpr indirect& operator=(U&& u);
`

[10](#assign-10)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6514)

*Constraints*: 

- [(10.1)](#assign-10.1)

is_same_v<remove_cvref_t<U>, indirect> is false,

- [(10.2)](#assign-10.2)

is_constructible_v<T, U> is true, and

- [(10.3)](#assign-10.3)

is_assignable_v<T&, U> is true[.](#assign-10.sentence-1)

[11](#assign-11)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6525)

*Effects*: If *this is valueless then
constructs an owned object of type T with std​::​forward<U>(u) using the allocator *alloc*[.](#assign-11.sentence-1)

Otherwise,
equivalent to **this = std​::​forward<U>(u)[.](#assign-11.sentence-2)

[12](#assign-12)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6533)

*Returns*: A reference to *this[.](#assign-12.sentence-1)

#### [20.4.1.6](#obs) Observers [[indirect.obs]](indirect.obs)

[ð](#lib:operator*,indirect)

`constexpr const T& operator*() const & noexcept;
constexpr T& operator*() & noexcept;
`

[1](#obs-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6547)

*Preconditions*: *this is not valueless[.](#obs-1.sentence-1)

[2](#obs-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6551)

*Returns*: **p*[.](#obs-2.sentence-1)

[ð](#lib:operator*,indirect_)

`constexpr const T&& operator*() const && noexcept;
constexpr T&& operator*() && noexcept;
`

[3](#obs-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6563)

*Preconditions*: *this is not valueless[.](#obs-3.sentence-1)

[4](#obs-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6567)

*Returns*: std​::​move(**p*)[.](#obs-4.sentence-1)

[ð](#lib:operator-%3e,indirect)

`constexpr const_pointer operator->() const noexcept;
constexpr pointer operator->() noexcept;
`

[5](#obs-5)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6579)

*Preconditions*: *this is not valueless[.](#obs-5.sentence-1)

[6](#obs-6)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6583)

*Returns*: *p*[.](#obs-6.sentence-1)

[ð](#lib:valueless_after_move,indirect)

`constexpr bool valueless_after_move() const noexcept;
`

[7](#obs-7)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6594)

*Returns*: true if *this is valueless, otherwise false[.](#obs-7.sentence-1)

[ð](#lib:get_allocator,indirect)

`constexpr allocator_type get_allocator() const noexcept;
`

[8](#obs-8)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6605)

*Returns*: *alloc*[.](#obs-8.sentence-1)

#### [20.4.1.7](#swap) Swap [[indirect.swap]](indirect.swap)

[ð](#lib:swap,indirect)

`constexpr void swap(indirect& other)
  noexcept(allocator_traits<Allocator>::propagate_on_container_swap::value ||
           allocator_traits<Allocator>::is_always_equal::value);
`

[1](#swap-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6620)

*Preconditions*: Ifallocator_traits<Allocator>​::​propagate_on_container_swap​::​value is true, thenAllocator meets the *Cpp17Swappable* requirements[.](#swap-1.sentence-1)

Otherwise get_allocator() == other.  
get_allocator() is true[.](#swap-1.sentence-2)

[2](#swap-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6628)

*Effects*: Swaps the states of *this and other,
exchanging owned objects or valueless states[.](#swap-2.sentence-1)

If allocator_traits<Allocator>​::​propagate_on_container_swap​::​value is true,
then the allocators of *this and other are exchanged by calling swap as described in [[swappable.requirements]](swappable.requirements "16.4.4.3 Swappable requirements")[.](#swap-2.sentence-2)

Otherwise,
the allocators are not swapped[.](#swap-2.sentence-3)

[*Note [1](#swap-note-1)*:

Does not call swap on the owned objects directly[.](#swap-2.sentence-4)

â *end note*]

[ð](#swap-itemdecl:2)

`constexpr void swap(indirect& lhs, indirect& rhs) noexcept(noexcept(lhs.swap(rhs)));
`

[3](#swap-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6650)

*Effects*: Equivalent to lhs.swap(rhs)[.](#swap-3.sentence-1)

#### [20.4.1.8](#relops) Relational operators [[indirect.relops]](indirect.relops)

[ð](#relops-itemdecl:1)

`template<class U, class AA>
  constexpr bool operator==(const indirect& lhs, const indirect<U, AA>& rhs)
    noexcept(noexcept(*lhs == *rhs));
`

[1](#relops-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6666)

*Mandates*: The expression *lhs == *rhs is well-formed and
its result is convertible to bool[.](#relops-1.sentence-1)

[2](#relops-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6671)

*Returns*: If lhs is valueless or rhs is valueless,lhs.valueless_after_move() == rhs.valueless_after_move();
otherwise *lhs == *rhs[.](#relops-2.sentence-1)

[ð](#relops-itemdecl:2)

`template<class U, class AA>
  constexpr synth-three-way-result<T, U>
    operator<=>(const indirect& lhs, const indirect<U, AA>& rhs);
`

[3](#relops-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6687)

*Returns*: If lhs is valueless or rhs is valueless,!lhs.valueless_after_move() <=> !rhs.valueless_after_move();
otherwise*synth-three-way*(*lhs, *rhs)[.](#relops-3.sentence-1)

#### [20.4.1.9](#comp.with.t) Comparison with T [[indirect.comp.with.t]](indirect.comp.with.t)

[ð](#comp.with.t-itemdecl:1)

`template<class U>
  constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(noexcept(*lhs == rhs));
`

[1](#comp.with.t-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6705)

*Mandates*: The expression *lhs == rhs is well-formed and
its result is convertible to bool[.](#comp.with.t-1.sentence-1)

[2](#comp.with.t-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6710)

*Returns*: If lhs is valueless, false;
otherwise *lhs == rhs[.](#comp.with.t-2.sentence-1)

[ð](#comp.with.t-itemdecl:2)

`template<class U>
  constexpr synth-three-way-result<T, U>
    operator<=>(const indirect& lhs, const U& rhs);
`

[3](#comp.with.t-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6725)

*Returns*: If lhs is valueless, strong_ordering​::​less;
otherwise *synth-three-way*(*lhs, rhs)[.](#comp.with.t-3.sentence-1)

#### [20.4.1.10](#hash) Hash support [[indirect.hash]](indirect.hash)

[ð](#lib:hash,indirect)

`template<class T, class Allocator>
struct hash<indirect<T, Allocator>>;
`

[1](#hash-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6740)

The specialization hash<indirect<T, Allocator>> is enabled ([[unord.hash]](unord.hash "22.10.19 Class template hash")) if and only if hash<T> is enabled[.](#hash-1.sentence-1)

When enabled for an object i of type indirect<T, Allocator>,hash<indirect<T, Allocator>>()(i) evaluates to
either the same value as hash<T>()(*i),
if i is not valueless;
otherwise to animplementation-defined
value[.](#hash-1.sentence-2)

The member functions are not guaranteed to be noexcept[.](#hash-1.sentence-3)
