32 concept allocator = std::copy_constructible<std::remove_cvref_t<T>>
33 and std::move_constructible<std::remove_cvref_t<T>>
34 and std::equality_comparable<std::remove_cvref_t<T>>
36 std::remove_cvref_t<T>& alloc,
37 typename std::remove_cvref_t<T>::value_type* p,
40 typename std::remove_cvref_t<T>::value_type;
43 } -> std::same_as<typename std::remove_cvref_t<T>::value_type*>;
44 { alloc.deallocate(p, n) } -> std::same_as<void>;
80 : m_storage(make_storage(
std::forward<A>(alloc)))
84 [[nodiscard]] T*
allocate(std::size_t n);
95 [[nodiscard]]
virtual T* allocate(std::size_t) = 0;
96 virtual void deallocate(T*, std::size_t) = 0;
97 [[nodiscard]]
virtual std::unique_ptr<interface> clone()
const = 0;
98 [[nodiscard]]
virtual bool equal(
const interface&)
const = 0;
99 virtual ~interface() =
default;
102 template <allocator A>
103 struct impl : interface
107 explicit impl(A alloc)
108 : m_alloc(
std::move(alloc))
112 [[nodiscard]] T* allocate(std::size_t n)
override
114 return m_alloc.allocate(n);
117 void deallocate(T* p, std::size_t n)
override
119 m_alloc.deallocate(p, n);
122 [[nodiscard]] std::unique_ptr<interface> clone()
const override
124 return std::make_unique<impl<A>>(m_alloc);
127 [[nodiscard]]
bool equal(
const interface& rhs)
const override
129 if (std::type_index(
typeid(*
this)) == std::type_index(
typeid(rhs)))
131 return m_alloc ==
static_cast<const impl<A>*
>(std::addressof(rhs))->m_alloc;
137 using storage_type = std::
138 variant<std::allocator<T>, std::pmr::polymorphic_allocator<T>, std::unique_ptr<interface>>;
141 [[nodiscard]] std::unique_ptr<interface> make_storage(A&& alloc)
const
143 return std::make_unique<impl<std::decay_t<A>>>(std::forward<A>(alloc));
147 requires can_any_allocator_sbo<A, T>
148 [[nodiscard]] A&& make_storage(A&& alloc)
const
150 return std::forward<A>(alloc);
153 [[nodiscard]] storage_type copy_storage(
const storage_type& rhs)
const
157 [](
const auto& arg) -> storage_type
159 return {std::decay_t<decltype(arg)>(arg)};
161 [](
const std::unique_ptr<interface>& arg) -> storage_type
163 return {arg->clone()};
171 [[nodiscard]]
decltype(
auto) visit_storage(F&& f)
176 using A = std::decay_t<
decltype(arg)>;
177 if constexpr (can_any_allocator_sbo<A, T>)
190 storage_type m_storage;