This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

888
cppdraft/indirect.md Normal file
View File

@@ -0,0 +1,888 @@
[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.1General[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.2Container 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.3Constructors"), 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.4Destructor"), destructorconstexpr ~indirect(); // [[indirect.assign]](#assign "20.4.1.5Assignment"), 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.6Observers"), 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.7Swap"), 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.8Relational 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.9Comparison 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.3Constructors"):
[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.3Swappable 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.19Class 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)