101 [[nodiscard]]
virtual T*
allocate(std::size_t) = 0;
103 [[nodiscard]]
virtual std::unique_ptr<interface> clone()
const = 0;
104 [[nodiscard]]
virtual bool equal(
const interface&)
const = 0;
105 virtual ~interface() =
default;
108 template <allocator A>
109 struct impl : interface
113 explicit impl(A alloc)
114 : m_alloc(
std::move(alloc))
118 [[nodiscard]] T* allocate(std::size_t n)
override
120 return m_alloc.allocate(n);
123 void deallocate(T* p, std::size_t n)
override
125 m_alloc.deallocate(p, n);
128 [[nodiscard]] std::unique_ptr<interface> clone()
const override
130 return std::make_unique<impl<A>>(m_alloc);
133 [[nodiscard]]
bool equal(
const interface& rhs)
const override
135 if (std::type_index(
typeid(*
this)) == std::type_index(
typeid(rhs)))
137 return m_alloc ==
static_cast<const impl<A>*
>(std::addressof(rhs))->m_alloc;
143 using storage_type = std::
144 variant<std::allocator<T>, std::pmr::polymorphic_allocator<T>, std::unique_ptr<interface>>;
147 [[nodiscard]] std::unique_ptr<interface> make_storage(A&& alloc)
const
149 return std::make_unique<impl<std::decay_t<A>>>(std::forward<A>(alloc));
153 requires can_any_allocator_sbo<A, T>
154 [[nodiscard]] A&& make_storage(A&& alloc)
const
156 return std::forward<A>(alloc);
159 [[nodiscard]] storage_type copy_storage(
const storage_type& rhs)
const
163 [](
const auto& arg) -> storage_type
165 return {std::decay_t<decltype(arg)>(arg)};
167 [](
const std::unique_ptr<interface>& arg) -> storage_type
169 return {arg->clone()};
177 [[nodiscard]]
decltype(
auto) visit_storage(F&& f)
182 using A = std::decay_t<
decltype(arg)>;
183 if constexpr (can_any_allocator_sbo<A, T>)
196 storage_type m_storage;
211 : m_storage(copy_storage(rhs.m_storage))
217 : m_storage(std::move(rhs.m_storage))
227 rhs.m_storage = std::allocator<T>();
233 return visit_storage(
243#if defined(_MSC_VER) && !defined(__clang__)
244 __declspec(no_sanitize_address)
246# if defined(__has_feature)
247# if __has_feature(address_sanitizer)
248 __attribute__((no_sanitize(
"address")))
255 return visit_storage(
259# pragma GCC diagnostic push
260# pragma GCC diagnostic ignored "-Wmismatched-new-delete"
261# pragma GCC diagnostic ignored "-Wnull-dereference"
265# pragma GCC diagnostic pop
284 using A = std::decay_t<
decltype(arg)>;
290 using A2 = std::decay_t<
decltype(arg2)>;
308 using A2 = std::decay_t<
decltype(arg2)>;
315 return arg->equal(*arg2);