[mem.composite.types]

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

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

### [20.4.1](#indirect) Class template indirect [[indirect]](indirect)

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

[1](#indirect.general-1)

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

An indirect object manages the lifetime of an owned object[.](#indirect.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[.](#indirect.general-1.sentence-2)

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

[2](#indirect.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[.](#indirect.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[.](#indirect.general-2.sentence-2)

[3](#indirect.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[.](#indirect.general-3.sentence-1)

[4](#indirect.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[.](#indirect.general-4.sentence-1)

The allocator *alloc* may be replaced
only via assignment or swap()[.](#indirect.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)](#indirect.general-4.1)

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

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

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

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

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

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

[5](#indirect.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[.](#indirect.general-5.sentence-1)

[6](#indirect.general-6)

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

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

[7](#indirect.general-7)

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

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

[8](#indirect.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[.](#indirect.general-8.sentence-1)

#### [20.4.1.2](#indirect.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]](#indirect.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]](#indirect.dtor "20.4.1.4 Destructor"), destructorconstexpr ~indirect(); // [[indirect.assign]](#indirect.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]](#indirect.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]](#indirect.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]](#indirect.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]](#indirect.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](#indirect.ctor) Constructors [[indirect.ctor]](indirect.ctor)

[1](#indirect.ctor-1)

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

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

[2](#indirect.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[.](#indirect.ctor-2.sentence-1)

[ð](#lib:indirect,constructor)

`constexpr explicit indirect();
`

[3](#indirect.ctor-3)

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

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

[4](#indirect.ctor-4)

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

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

[5](#indirect.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*[.](#indirect.ctor-5.sentence-1)

[ð](#lib:indirect,constructor_)

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

[6](#indirect.ctor-6)

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

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

[7](#indirect.ctor-7)

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

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

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

[ð](#lib:indirect,constructor__)

`constexpr indirect(const indirect& other);
`

[8](#indirect.ctor-8)

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

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

[9](#indirect.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*)[.](#indirect.ctor-9.sentence-1)

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

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

[ð](#lib:indirect,constructor___)

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

[10](#indirect.ctor-10)

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

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

[11](#indirect.ctor-11)

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

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

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

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

[ð](#lib:indirect,constructor____)

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

[12](#indirect.ctor-12)

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

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

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

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

[13](#indirect.ctor-13)

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

*Postconditions*: other is valueless[.](#indirect.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](#indirect.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[.](#indirect.ctor-14.sentence-1)

[15](#indirect.ctor-15)

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

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

If other is valueless, *this is valueless[.](#indirect.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[.](#indirect.ctor-15.sentence-3)

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

[16](#indirect.ctor-16)

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

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

[ð](#lib:indirect,constructor______)

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

[17](#indirect.ctor-17)

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

*Constraints*: 

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

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

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

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

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

is_constructible_v<T, U> is true, and

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

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

[18](#indirect.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*[.](#indirect.ctor-18.sentence-1)

[ð](#lib:indirect,constructor_______)

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

[19](#indirect.ctor-19)

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

*Constraints*: 

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

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

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

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

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

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

[20](#indirect.ctor-20)

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

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

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

[ð](#lib:indirect,constructor________)

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

[21](#indirect.ctor-21)

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

*Constraints*: 

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

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

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

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

[22](#indirect.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*[.](#indirect.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](#indirect.ctor-23)

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

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

[24](#indirect.ctor-24)

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

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

Constructs an owned object of type T withstd​::​forward<Us>(us)...,
using the allocator *alloc*[.](#indirect.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](#indirect.ctor-25)

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

*Constraints*: 

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

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

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

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

[26](#indirect.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*[.](#indirect.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](#indirect.ctor-27)

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

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

[28](#indirect.ctor-28)

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

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

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

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

[ð](#lib:indirect,destructor)

`constexpr ~indirect();
`

[1](#indirect.dtor-1)

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

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

[2](#indirect.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[.](#indirect.dtor-2.sentence-1)

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

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

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

[1](#indirect.assign-1)

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

*Mandates*: 

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

is_copy_assignable_v<T> is true, and

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

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

[2](#indirect.assign-2)

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

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

Otherwise:

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

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

- [(2.2)](#indirect.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[.](#indirect.assign-2.2.sentence-1)

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

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

- [(2.4)](#indirect.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[.](#indirect.assign-2.4.sentence-1)

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

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

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

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

[3](#indirect.assign-3)

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

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

[4](#indirect.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[.](#indirect.assign-4.sentence-1)

If an exception is thrown during
the call to T's selected copy constructor, no effect[.](#indirect.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[.](#indirect.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](#indirect.assign-5)

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

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

[6](#indirect.assign-6)

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

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

Otherwise:

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

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

- [(6.2)](#indirect.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[.](#indirect.assign-6.2.sentence-1)

- [(6.3)](#indirect.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[.](#indirect.assign-6.3.sentence-1)

- [(6.4)](#indirect.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[.](#indirect.assign-6.4.sentence-1)

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

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

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

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

[7](#indirect.assign-7)

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

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

[8](#indirect.assign-8)

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

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

[9](#indirect.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[.](#indirect.assign-9.sentence-1)

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

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

[10](#indirect.assign-10)

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

*Constraints*: 

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

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

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

is_constructible_v<T, U> is true, and

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

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

[11](#indirect.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*[.](#indirect.assign-11.sentence-1)

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

[12](#indirect.assign-12)

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

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

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

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

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

[1](#indirect.obs-1)

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

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

[2](#indirect.obs-2)

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

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

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

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

[3](#indirect.obs-3)

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

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

[4](#indirect.obs-4)

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

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

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

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

[5](#indirect.obs-5)

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

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

[6](#indirect.obs-6)

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

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

[ð](#lib:valueless_after_move,indirect)

`constexpr bool valueless_after_move() const noexcept;
`

[7](#indirect.obs-7)

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

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

[ð](#lib:get_allocator,indirect)

`constexpr allocator_type get_allocator() const noexcept;
`

[8](#indirect.obs-8)

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

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

#### [20.4.1.7](#indirect.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](#indirect.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[.](#indirect.swap-1.sentence-1)

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

[2](#indirect.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[.](#indirect.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")[.](#indirect.swap-2.sentence-2)

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

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

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

â *end note*]

[ð](#indirect.swap-itemdecl:2)

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

[3](#indirect.swap-3)

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

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

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

[ð](#indirect.relops-itemdecl:1)

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

[1](#indirect.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[.](#indirect.relops-1.sentence-1)

[2](#indirect.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[.](#indirect.relops-2.sentence-1)

[ð](#indirect.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](#indirect.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)[.](#indirect.relops-3.sentence-1)

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

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

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

[1](#indirect.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[.](#indirect.comp.with.t-1.sentence-1)

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

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

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

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

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

[3](#indirect.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)[.](#indirect.comp.with.t-3.sentence-1)

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

[ð](#lib:hash,indirect)

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

[1](#indirect.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[.](#indirect.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[.](#indirect.hash-1.sentence-2)

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

### [20.4.2](#polymorphic) Class template polymorphic [[polymorphic]](polymorphic)

#### [20.4.2.1](#polymorphic.general) General [[polymorphic.general]](polymorphic.general)

[1](#polymorphic.general-1)

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

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

A polymorphic object may own objects of
different types at different points in its lifetime[.](#polymorphic.general-1.sentence-2)

A polymorphic object is[*valueless*](#def:valueless,polymorphic_object "20.4.2.1 General [polymorphic.general]") if it has no owned object[.](#polymorphic.general-1.sentence-3)

A polymorphic object may become valueless only after it has been moved from[.](#polymorphic.general-1.sentence-4)

[2](#polymorphic.general-2)

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

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

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

[3](#polymorphic.general-3)

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

Constructing an owned object of type U 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* points to storage suitable for an owned object of type U[.](#polymorphic.general-3.sentence-1)

[4](#polymorphic.general-4)

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

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

The allocator may be replaced only via
assignment or swap()[.](#polymorphic.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)](#polymorphic.general-4.1)

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

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

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

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

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

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

[5](#polymorphic.general-5)

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

A program that instantiates the definition of polymorphic for
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[.](#polymorphic.general-5.sentence-1)

[6](#polymorphic.general-6)

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

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

[7](#polymorphic.general-7)

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

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

[8](#polymorphic.general-8)

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

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

#### [20.4.2.2](#polymorphic.syn) Synopsis [[polymorphic.syn]](polymorphic.syn)

[ð](#lib:polymorphic)

namespace std {template<class T, class Allocator = allocator<T>>class polymorphic {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; // [[polymorphic.ctor]](#polymorphic.ctor "20.4.2.3 Constructors"), constructorsconstexpr explicit polymorphic(); constexpr explicit polymorphic(allocator_arg_t, const Allocator& a); constexpr polymorphic(const polymorphic& other); constexpr polymorphic(allocator_arg_t, const Allocator& a, const polymorphic& other); constexpr polymorphic(polymorphic&& other) noexcept; constexpr polymorphic(allocator_arg_t, const Allocator& a, polymorphic&& other)noexcept(*see below*); template<class U = T>constexpr explicit polymorphic(U&& u); template<class U = T>constexpr explicit polymorphic(allocator_arg_t, const Allocator& a, U&& u); template<class U, class... Ts>constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts); template<class U, class... Ts>constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
 in_place_type_t<U>, Ts&&... ts); template<class U, class I, class... Us>constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us); template<class U, class I, class... Us>constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
 in_place_type_t<U>, initializer_list<I> ilist, Us&&... us); // [[polymorphic.dtor]](#polymorphic.dtor "20.4.2.4 Destructor"), destructorconstexpr ~polymorphic(); // [[polymorphic.assign]](#polymorphic.assign "20.4.2.5 Assignment"), assignmentconstexpr polymorphic& operator=(const polymorphic& other); constexpr polymorphic& operator=(polymorphic&& other) noexcept(*see below*); // [[polymorphic.obs]](#polymorphic.obs "20.4.2.6 Observers"), observersconstexpr 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; // [[polymorphic.swap]](#polymorphic.swap "20.4.2.7 Swap"), swapconstexpr void swap(polymorphic& other) noexcept(*see below*); friend constexpr void swap(polymorphic& lhs, polymorphic& rhs) noexcept(*see below*); private: Allocator *alloc* = Allocator(); // *exposition only*};}

#### [20.4.2.3](#polymorphic.ctor) Constructors [[polymorphic.ctor]](polymorphic.ctor)

[1](#polymorphic.ctor-1)

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

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

[2](#polymorphic.ctor-2)

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

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

[ð](#lib:polymorphic,constructor)

`constexpr explicit polymorphic();
`

[3](#polymorphic.ctor-3)

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

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

[4](#polymorphic.ctor-4)

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

*Mandates*: 

- [(4.1)](#polymorphic.ctor-4.1)

is_default_constructible_v<T> is true, and

- [(4.2)](#polymorphic.ctor-4.2)

is_copy_constructible_v<T> is true[.](#polymorphic.ctor-4.sentence-1)

[5](#polymorphic.ctor-5)

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

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

[ð](#lib:indirect,constructor____________)

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

[6](#polymorphic.ctor-6)

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

*Mandates*: 

- [(6.1)](#polymorphic.ctor-6.1)

is_default_constructible_v<T> is true, and

- [(6.2)](#polymorphic.ctor-6.2)

is_copy_constructible_v<T> is true[.](#polymorphic.ctor-6.sentence-1)

[7](#polymorphic.ctor-7)

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

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

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

[ð](#lib:polymorphic,constructor_)

`constexpr polymorphic(const polymorphic& other);
`

[8](#polymorphic.ctor-8)

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

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

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

Otherwise,
constructs an owned object of type U, whereU is the type of the owned object in other, with
the owned object in other using the allocator *alloc*[.](#polymorphic.ctor-8.sentence-3)

[ð](#lib:polymorphic,constructor__)

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

[9](#polymorphic.ctor-9)

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

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

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

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

[ð](#lib:polymorphic,constructor___)

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

[10](#polymorphic.ctor-10)

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

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

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

Otherwise,
either *this takes ownership of the owned object of other or,
owns an object of the same type
constructed from the owned object of other considering that owned object as an rvalue,
using the allocator *alloc*[.](#polymorphic.ctor-10.sentence-3)

[ð](#lib:polymorphic,constructor____)

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

[11](#polymorphic.ctor-11)

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

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

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

Otherwise,
if *alloc* == other.*alloc* is true,
either constructs an object of type polymorphic that
owns the owned object of other,
making other valueless; or,
owns an object of the same type constructed from
the owned object of other considering that owned object as an rvalue[.](#polymorphic.ctor-11.sentence-3)

Otherwise,
if *alloc* != other.*alloc* is true,
constructs an object of type polymorphic,
considering the owned object in other as an rvalue,
using the allocator *alloc*[.](#polymorphic.ctor-11.sentence-4)

[ð](#lib:polymorphic,constructor_____)

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

[12](#polymorphic.ctor-12)

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

*Constraints*: Where UU is remove_cvref_t<U>,

- [(12.1)](#polymorphic.ctor-12.1)

is_same_v<UU, polymorphic> is false,

- [(12.2)](#polymorphic.ctor-12.2)

derived_from<UU, T> is true,

- [(12.3)](#polymorphic.ctor-12.3)

is_constructible_v<UU, U> is true,

- [(12.4)](#polymorphic.ctor-12.4)

is_copy_constructible_v<UU> is true,

- [(12.5)](#polymorphic.ctor-12.5)

UU is not a specialization of in_place_type_t, and

- [(12.6)](#polymorphic.ctor-12.6)

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

[13](#polymorphic.ctor-13)

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

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

[ð](#lib:polymorphic,constructor______)

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

[14](#polymorphic.ctor-14)

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

*Constraints*: Where UU is remove_cvref_t<U>,

- [(14.1)](#polymorphic.ctor-14.1)

is_same_v<UU, polymorphic> is false,

- [(14.2)](#polymorphic.ctor-14.2)

derived_from<UU, T> is true,

- [(14.3)](#polymorphic.ctor-14.3)

is_constructible_v<UU, U> is true,

- [(14.4)](#polymorphic.ctor-14.4)

is_copy_constructible_v<UU> is true, and

- [(14.5)](#polymorphic.ctor-14.5)

UU is not a specialization of in_place_type_t[.](#polymorphic.ctor-14.sentence-1)

[15](#polymorphic.ctor-15)

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

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

Constructs an owned object of type UU with std​::​forward<U>(u) using the allocator *alloc*[.](#polymorphic.ctor-15.sentence-2)

[ð](#lib:polymorphic,constructor_______)

`template<class U, class... Ts>
  constexpr explicit polymorphic(in_place_type_t<U>, Ts&&... ts);
`

[16](#polymorphic.ctor-16)

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

*Constraints*: 

- [(16.1)](#polymorphic.ctor-16.1)

is_same_v<remove_cvref_t<U>, U> is true,

- [(16.2)](#polymorphic.ctor-16.2)

derived_from<U, T> is true,

- [(16.3)](#polymorphic.ctor-16.3)

is_constructible_v<U, Ts...> is true,

- [(16.4)](#polymorphic.ctor-16.4)

is_copy_constructible_v<U> is true, and

- [(16.5)](#polymorphic.ctor-16.5)

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

[17](#polymorphic.ctor-17)

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

*Effects*: Constructs an owned object of type U withstd​::​forward<Ts>(ts)... using the allocator *alloc*[.](#polymorphic.ctor-17.sentence-1)

[ð](#lib:polymorphic,constructor________)

`template<class U, class... Ts>
  constexpr explicit polymorphic(allocator_arg_t, const Allocator& a,
                                 in_place_type_t<U>, Ts&&... ts);
`

[18](#polymorphic.ctor-18)

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

*Constraints*: 

- [(18.1)](#polymorphic.ctor-18.1)

is_same_v<remove_cvref_t<U>, U> is true,

- [(18.2)](#polymorphic.ctor-18.2)

derived_from<U, T> is true,

- [(18.3)](#polymorphic.ctor-18.3)

is_constructible_v<U, Ts...> is true, and

- [(18.4)](#polymorphic.ctor-18.4)

is_copy_constructible_v<U> is true[.](#polymorphic.ctor-18.sentence-1)

[19](#polymorphic.ctor-19)

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

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

Constructs an owned object of type U withstd​::​forward<Ts>(ts)... using the allocator *alloc*[.](#polymorphic.ctor-19.sentence-2)

[ð](#lib:polymorphic,constructor_________)

`template<class U, class I, class... Us>
  constexpr explicit polymorphic(in_place_type_t<U>, initializer_list<I> ilist, Us&&... us);
`

[20](#polymorphic.ctor-20)

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

*Constraints*: 

- [(20.1)](#polymorphic.ctor-20.1)

is_same_v<remove_cvref_t<U>, U> is true,

- [(20.2)](#polymorphic.ctor-20.2)

derived_from<U, T> is true,

- [(20.3)](#polymorphic.ctor-20.3)

is_constructible_v<U, initializer_list<I>&, Us...> is true,

- [(20.4)](#polymorphic.ctor-20.4)

is_copy_constructible_v<U> is true, and

- [(20.5)](#polymorphic.ctor-20.5)

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

[21](#polymorphic.ctor-21)

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

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

[ð](#lib:polymorphic,constructor__________)

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

[22](#polymorphic.ctor-22)

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

*Constraints*: 

- [(22.1)](#polymorphic.ctor-22.1)

is_same_v<remove_cvref_t<U>, U> is true,

- [(22.2)](#polymorphic.ctor-22.2)

derived_from<U, T> is true,

- [(22.3)](#polymorphic.ctor-22.3)

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

- [(22.4)](#polymorphic.ctor-22.4)

is_copy_constructible_v<U> is true[.](#polymorphic.ctor-22.sentence-1)

[23](#polymorphic.ctor-23)

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

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

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

#### [20.4.2.4](#polymorphic.dtor) Destructor [[polymorphic.dtor]](polymorphic.dtor)

[ð](#lib:polymorphic,destructor)

`constexpr ~polymorphic();
`

[1](#polymorphic.dtor-1)

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

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

[2](#polymorphic.dtor-2)

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

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

#### [20.4.2.5](#polymorphic.assign) Assignment [[polymorphic.assign]](polymorphic.assign)

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

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

[1](#polymorphic.assign-1)

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

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

[2](#polymorphic.assign-2)

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

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

Otherwise:

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

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

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

  If other is not valueless,
a new owned object is constructed in *this usingallocator_traits<Allocator>​::​construct 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[.](#polymorphic.assign-2.2.sentence-1)

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

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

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

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

[3](#polymorphic.assign-3)

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

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

[4](#polymorphic.assign-4)

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

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

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

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

[5](#polymorphic.assign-5)

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

*Mandates*: If allocator_traits<Allocator>​::​is_always_equal​::​value is false,T is a complete type[.](#polymorphic.assign-5.sentence-1)

[6](#polymorphic.assign-6)

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

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

Otherwise:

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

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

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

  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[.](#polymorphic.assign-6.2.sentence-1)

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

  Otherwise,
if *alloc* != other.*alloc* is true;
if other is not valueless,
a new owned object is constructed in *this using allocator_traits<Allocator>​::​construct with
the owned object from other as the argument as an rvalue,
using either the allocator in *this or
the allocator in other if the allocator needs updating[.](#polymorphic.assign-6.3.sentence-1)

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

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

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

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

[7](#polymorphic.assign-7)

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

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

[8](#polymorphic.assign-8)

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

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

#### [20.4.2.6](#polymorphic.obs) Observers [[polymorphic.obs]](polymorphic.obs)

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

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

[1](#polymorphic.obs-1)

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

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

[2](#polymorphic.obs-2)

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

*Returns*: A reference to the owned object[.](#polymorphic.obs-2.sentence-1)

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

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

[3](#polymorphic.obs-3)

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

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

[4](#polymorphic.obs-4)

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

*Returns*: A pointer to the owned object[.](#polymorphic.obs-4.sentence-1)

[ð](#lib:valueless_after_move,polymorphic)

`constexpr bool valueless_after_move() const noexcept;
`

[5](#polymorphic.obs-5)

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

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

[ð](#lib:get_allocator,polymorphic)

`constexpr allocator_type get_allocator() const noexcept;
`

[6](#polymorphic.obs-6)

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

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

#### [20.4.2.7](#polymorphic.swap) Swap [[polymorphic.swap]](polymorphic.swap)

[ð](#lib:swap,polymorphic)

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

[1](#polymorphic.swap-1)

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

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

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

[2](#polymorphic.swap-2)

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

*Effects*: Swaps the states of *this and other,
exchanging owned objects or valueless states[.](#polymorphic.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")[.](#polymorphic.swap-2.sentence-2)

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

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

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

â *end note*]

[ð](#polymorphic.swap-itemdecl:2)

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

[3](#polymorphic.swap-3)

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

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