95 [[nodiscard]]
virtual T*
allocate(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 reinterpret_cast<T*
>(m_alloc.allocate(n));
118 void deallocate(T* p, std::size_t n)
override
121# pragma GCC diagnostic push
122# pragma GCC diagnostic ignored "-Wcast-align"
124 m_alloc.deallocate(
reinterpret_cast<A::value_type*
>(p), n);
126# pragma GCC diagnostic pop
130 [[nodiscard]] std::unique_ptr<interface> clone()
const override
132 return std::make_unique<impl<A>>(m_alloc);
135 [[nodiscard]]
bool equal(
const interface& rhs)
const override
137 if (std::type_index(
typeid(*
this)) == std::type_index(
typeid(rhs)))
139 return m_alloc ==
static_cast<const impl<A>*
>(std::addressof(rhs))->m_alloc;
145 using storage_type = std::
146 variant<std::allocator<T>, std::pmr::polymorphic_allocator<T>, std::unique_ptr<interface>>;
149 [[nodiscard]] std::unique_ptr<interface> make_storage(A&& alloc)
const
151 return std::make_unique<impl<std::decay_t<A>>>(std::forward<A>(alloc));
155 requires can_any_allocator_sbo<A, T>
156 [[nodiscard]] A&& make_storage(A&& alloc)
const
158 return std::forward<A>(alloc);
161 [[nodiscard]] storage_type copy_storage(
const storage_type& rhs)
const
165 [](
const auto& arg) -> storage_type
167 return {std::decay_t<decltype(arg)>(arg)};
169 [](
const std::unique_ptr<interface>& arg) -> storage_type
171 return {arg->clone()};
179 [[nodiscard]]
decltype(
auto) visit_storage(F&& f)
184 using A = std::decay_t<
decltype(arg)>;
185 if constexpr (can_any_allocator_sbo<A, T>)
198 storage_type m_storage;
213 : m_storage(copy_storage(rhs.m_storage))
220 return visit_storage(
230#if defined(_MSC_VER) && !defined(__clang__)
231 __declspec(no_sanitize_address)
233# if defined(__has_feature)
234# if __has_feature(address_sanitizer)
235 __attribute__((no_sanitize(
"address")))
242 return visit_storage(
246# pragma GCC diagnostic push
247# pragma GCC diagnostic ignored "-Wmismatched-new-delete"
248# pragma GCC diagnostic ignored "-Wnull-dereference"
252# pragma GCC diagnostic pop
271 using A = std::decay_t<
decltype(arg)>;
277 using A2 = std::decay_t<
decltype(arg2)>;
295 using A2 = std::decay_t<
decltype(arg2)>;
302 return arg->equal(*arg2);