103 [[nodiscard]]
virtual T*
allocate(std::size_t) = 0;
105 [[nodiscard]]
virtual std::unique_ptr<interface> clone()
const = 0;
106 [[nodiscard]]
virtual bool equal(
const interface&)
const = 0;
107 virtual ~interface() =
default;
110 template <allocator A>
111 struct impl : interface
115 constexpr explicit impl(A alloc)
116 : m_alloc(
std::move(alloc))
120 [[nodiscard]]
constexpr T* allocate(std::size_t n)
override
122 return m_alloc.allocate(n);
125 constexpr void deallocate(T* p, std::size_t n)
override
127 m_alloc.deallocate(p, n);
130 [[nodiscard]] std::unique_ptr<interface> clone()
const override
132 return std::make_unique<impl<A>>(m_alloc);
135 [[nodiscard]]
constexpr 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::variant<
147 std::pmr::polymorphic_allocator<T>,
148 xsimd::aligned_allocator<T>,
149 std::unique_ptr<interface>>;
152 [[nodiscard]] std::unique_ptr<interface> make_storage(A&& alloc)
const
154 return std::make_unique<impl<std::decay_t<A>>>(std::forward<A>(alloc));
158 requires can_any_allocator_sbo<A, T>
159 [[nodiscard]]
constexpr A&& make_storage(A&& alloc)
const
161 return std::forward<A>(alloc);
164 [[nodiscard]]
constexpr storage_type copy_storage(
const storage_type& rhs)
const
168 [](
const auto& arg) -> storage_type
170 return {std::decay_t<decltype(arg)>(arg)};
172 [](
const std::unique_ptr<interface>& arg) -> storage_type
174 return {arg->clone()};
182 [[nodiscard]]
constexpr decltype(
auto) visit_storage(F&& f)
187 using A = std::decay_t<
decltype(arg)>;
188 if constexpr (can_any_allocator_sbo<A, T>)
201 storage_type m_storage;
210 : m_storage(make_storage(
xsimd::aligned_allocator<T>()))
216 : m_storage(copy_storage(rhs.m_storage))
222 : m_storage(std::move(rhs.m_storage))
238 return visit_storage(
248#if defined(_MSC_VER) && !defined(__clang__)
249 __declspec(no_sanitize_address)
251# if defined(__has_feature)
252# if __has_feature(address_sanitizer)
253 __attribute__((no_sanitize(
"address")))
259 return visit_storage(
263# pragma GCC diagnostic push
264# pragma GCC diagnostic ignored "-Wmismatched-new-delete"
265# pragma GCC diagnostic ignored "-Wnull-dereference"
269# pragma GCC diagnostic pop
288 using A = std::decay_t<
decltype(arg)>;
294 using A2 = std::decay_t<
decltype(arg2)>;
312 using A2 = std::decay_t<
decltype(arg2)>;
319 return arg->equal(*arg2);