[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, if the type allocator_traits​::​value_type is not the same type as T, the program is ill-formed[.](#general-2.sentence-1) Every object of type indirect 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​::​construct(a, *p*, args...) whereargs is an expression pack,a is an allocator, and*p* is a pointer obtained by calling allocator_traits​::​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​::​propagate_on_container_copy_assignment​::​value, or - [(4.2)](#general-4.2) allocator_traits​::​propagate_on_container_move_assignment​::​value, or - [(4.3)](#general-4.3) allocator_traits​::​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 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 indirect {public:using value_type = T; using allocator_type = Allocator; using pointer = typename allocator_traits::pointer; using const_pointer = typename allocator_traits::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*); templateconstexpr explicit indirect(U&& u); templateconstexpr explicit indirect(allocator_arg_t, const Allocator& a, U&& u); templateconstexpr explicit indirect(in_place_t, Us&&... us); templateconstexpr explicit indirect(allocator_arg_t, const Allocator& a, in_place_t, Us&&... us); templateconstexpr explicit indirect(in_place_t, initializer_list ilist, Us&&... us); templateconstexpr explicit indirect(allocator_arg_t, const Allocator& a, in_place_t, initializer_list 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*); templateconstexpr 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 operatorstemplatefriend constexpr bool operator==(const indirect& lhs, const indirect& rhs)noexcept(*see below*); templatefriend constexpr auto operator<=>(const indirect& lhs, const indirect& rhs)-> *synth-three-way-result*; // [[indirect.comp.with.t]](#comp.with.t "20.4.1.9 Comparison with T"), comparison with Ttemplatefriend constexpr bool operator==(const indirect& lhs, const U& rhs) noexcept(*see below*); templatefriend constexpr auto operator<=>(const indirect& lhs, const U& rhs)-> *synth-three-way-result*; private: pointer *p*; // *exposition only* Allocator *alloc* = Allocator(); // *exposition only*}; template indirect(Value) -> indirect; template indirect(allocator_arg_t, Allocator, Value)-> indirect::template rebind_alloc>;} #### [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​::​allocate orallocator_traits​::​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 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 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 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 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​::​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 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::is_always_equal::value); ` [14](#ctor-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6170) *Mandates*: If allocator_traits​::​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 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, indirect> is false, - [(17.2)](#ctor-17.2) is_same_v, in_place_t> is false, - [(17.3)](#ctor-17.3) is_constructible_v is true, and - [(17.4)](#ctor-17.4) is_default_constructible_v 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), using the allocator *alloc*[.](#ctor-18.sentence-1) [🔗](#lib:indirect,constructor_______) `template 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, indirect> is false, - [(19.2)](#ctor-19.2) is_same_v, in_place_t> is false, and - [(19.3)](#ctor-19.3) is_constructible_v 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), using the allocator *alloc*[.](#ctor-20.sentence-2) [🔗](#lib:indirect,constructor________) `template 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 is true, and - [(21.2)](#ctor-21.2) is_default_constructible_v 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)..., using the allocator *alloc*[.](#ctor-22.sentence-1) [🔗](#lib:indirect,constructor_________) `template 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 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)..., using the allocator *alloc*[.](#ctor-24.sentence-2) [🔗](#lib:indirect,constructor__________) `template constexpr explicit indirect(in_place_t, initializer_list 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&, Us...> is true, and - [(25.2)](#ctor-25.2) is_default_constructible_v 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)..., using the allocator *alloc*[.](#ctor-26.sentence-1) [🔗](#lib:indirect,constructor___________) `template constexpr explicit indirect(allocator_arg_t, const Allocator& a, in_place_t, initializer_list ilist, Us&&... us); ` [27](#ctor-27) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6318) *Constraints*: is_constructible_v&, 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)..., 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​::​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 is true, and - [(1.2)](#assign-1.2) is_copy_constructible_v 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​::​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​::​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​::​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​::​ 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::propagate_on_container_move_assignment::value || allocator_traits::is_always_equal::value); ` [5](#assign-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6440) *Mandates*: is_copy_constructible_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​::​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​::​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​::​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​::​ 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 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, indirect> is false, - [(10.2)](#assign-10.2) is_constructible_v is true, and - [(10.3)](#assign-10.3) is_assignable_v 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) using the allocator *alloc*[.](#assign-11.sentence-1) Otherwise, equivalent to **this = std​::​forward(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::propagate_on_container_swap::value || allocator_traits::is_always_equal::value); ` [1](#swap-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6620) *Preconditions*: Ifallocator_traits​::​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​::​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 constexpr bool operator==(const indirect& lhs, const indirect& 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 constexpr synth-three-way-result operator<=>(const indirect& lhs, const indirect& 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 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 constexpr synth-three-way-result 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 struct hash>; ` [1](#hash-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L6740) The specialization hash> is enabled ([[unord.hash]](unord.hash "22.10.19 Class template hash")) if and only if hash is enabled[.](#hash-1.sentence-1) When enabled for an object i of type indirect,hash>()(i) evaluates to either the same value as hash()(*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)