3 #include "../utility/empty_base.h"
4 #include "../utility/meta.h"
10 #include <type_traits>
21 template<
typename P,
typename F>
25 static_assert(detail::has_no_value_type_v<P>,
"Building on top of typed allocators is not allowed. Use allocators without a type");
26 static_assert(detail::has_no_value_type_v<F>,
"Building on top of typed allocators is not allowed. Use allocators without a type");
27 static_assert(detail::has_owns_v<P>,
"The primary allocator is required to have an 'owns(void*)' method");
37 template<
typename Primary,
38 typename = std::enable_if_t<std::is_constructible_v<P, Primary>>>
40 noexcept(std::is_nothrow_constructible_v<P, Primary> && std::is_nothrow_default_constructible_v<F>) :
41 m_Primary(std::forward<Primary>(primary)),
47 template<
typename Primary,
typename Fallback,
48 typename = std::enable_if_t<
49 std::is_constructible_v<P, Primary> &&
50 std::is_constructible_v<F, Fallback>>>
52 noexcept(std::is_nothrow_constructible_v<P, Primary> && std::is_nothrow_constructible_v<F, Fallback>) :
53 m_Primary(std::forward<Primary>(primary)),
54 m_Fallback(std::forward<Fallback>(
fallback)) {}
59 template<
typename... Args,
60 typename = std::enable_if_t<
61 std::is_constructible_v<P, Args...>>>
62 explicit fallback(std::tuple<Args...>&& primary)
63 noexcept(std::is_nothrow_constructible_v<P, Args...> && std::is_nothrow_default_constructible_v<F>) :
64 m_Primary(std::make_from_tuple<P>(std::forward<std::tuple<Args...>>(primary))),
70 template<
typename... ArgsP,
typename... ArgsF,
71 typename = std::enable_if_t<
72 std::is_constructible_v<P, ArgsP...>&&
73 std::is_constructible_v<F, ArgsF...>>>
75 noexcept(std::is_nothrow_constructible_v<P, ArgsP...> && std::is_nothrow_constructible_v<F, ArgsF...>) :
76 m_Primary(std::make_from_tuple<P>(std::forward<std::tuple<ArgsP...>>(primary))),
77 m_Fallback(std::make_from_tuple<F>(std::forward<std::tuple<ArgsF...>>(
fallback))) {}
88 noexcept(detail::has_nothrow_equal_v<P> && detail::has_nothrow_equal_v<F>)
90 return m_Primary == rhs.m_Primary && m_Fallback == rhs.m_Fallback;
94 noexcept(detail::has_nothrow_not_equal_v<P>&& detail::has_nothrow_not_equal_v<F>)
96 return m_Primary != rhs.m_Primary || m_Fallback != rhs.m_Fallback;
99 #pragma region Allocation
101 noexcept(detail::has_nothrow_allocate_v<P> && detail::has_nothrow_allocate_v<F>)
103 void* ptr = m_Primary.allocate(n);
105 return m_Fallback.allocate(n);
110 noexcept(detail::has_nothrow_deallocate_v<P>&& detail::has_nothrow_deallocate_v<F>)
112 if (m_Primary.owns(p))
114 m_Primary.deallocate(p, n);
118 m_Fallback.deallocate(p, n);
122 #pragma region Construction
123 template<
typename T,
typename... Args>
126 (!detail::has_construct_v<P, T*, Args...> || detail::has_nothrow_construct_v<P, T*, Args...>) &&
127 (!detail::has_construct_v<F, T*, Args...> || detail::has_nothrow_construct_v<F, T*, Args...>) &&
128 std::is_nothrow_constructible_v<T, Args...>)
130 bool owned = m_Primary.owns(p);
132 if constexpr (detail::has_construct_v<P, T*, Args...>)
136 m_Primary.construct(p, std::forward<Args>(args)...);
141 if constexpr (detail::has_construct_v<F, T*, Args...>)
145 m_Fallback.construct(p, std::forward<Args>(args)...);
150 ::new(p) T(std::forward<Args>(args)...);
154 typename std::enable_if<detail::has_destroy_v<P, T*> || detail::has_destroy_v<F, T*>,
void>::type
156 (!detail::has_destroy_v<P, T*> || detail::has_nothrow_destroy_v<P, T*>) &&
157 (!detail::has_destroy_v<F, T*> || detail::has_nothrow_destroy_v<F, T*>) &&
158 std::is_nothrow_destructible_v<T>)
160 bool owned = m_Primary.owns(p);
162 if constexpr (detail::has_destroy_v<P, T*>)
166 m_Primary.destroy(p);
171 if constexpr (detail::has_destroy_v<F, T*>)
175 m_Fallback.destroy(p);
184 #pragma region Utility
185 template<
typename Primary = P,
typename Fallback = F>
186 typename std::enable_if<detail::has_max_size_v<Primary> && detail::has_max_size_v<Fallback>,
size_type>::type
190 return (std::max)(m_Primary.max_size(), m_Fallback.max_size());
193 template<
typename Primary = P,
typename Fallback = F>
194 typename std::enable_if<detail::has_owns_v<Primary> && detail::has_owns_v<Fallback>,
bool>::type
196 noexcept(detail::has_nothrow_owns_v<Primary> && detail::has_nothrow_owns_v<Fallback>)
198 if (m_Primary.owns(p))
201 return m_Fallback.owns(p);
An allocator which delegates allocations between 2 different allocators. It first attempts to allocat...
Definition: fallback.h:23
fallback(std::tuple< ArgsP... > &&primary, std::tuple< ArgsF... > &&fallback) noexcept(std::is_nothrow_constructible_v< P, ArgsP... > &&std::is_nothrow_constructible_v< F, ArgsF... >)
Constructor for forwarding a tuple of arguments to the primary and fallback allocators.
Definition: fallback.h:74
fallback(fallback &&)=default
void * allocate(size_t n) noexcept(detail::has_nothrow_allocate_v< P > &&detail::has_nothrow_allocate_v< F >)
Definition: fallback.h:100
fallback(std::tuple< Args... > &&primary) noexcept(std::is_nothrow_constructible_v< P, Args... > &&std::is_nothrow_default_constructible_v< F >)
Constructor for forwarding a tuple of arguments to the primary allocator.
Definition: fallback.h:62
fallback & operator=(fallback &&)=default
bool operator!=(const fallback &rhs) const noexcept(detail::has_nothrow_not_equal_v< P > &&detail::has_nothrow_not_equal_v< F >)
Definition: fallback.h:93
fallback(const fallback &)=default
fallback(Primary &&primary, Fallback &&fallback) noexcept(std::is_nothrow_constructible_v< P, Primary > &&std::is_nothrow_constructible_v< F, Fallback >)
Constructor for forwarding a single argument to the primary and fallback allocators.
Definition: fallback.h:51
bool operator==(const fallback &rhs) const noexcept(detail::has_nothrow_equal_v< P > &&detail::has_nothrow_equal_v< F >)
Definition: fallback.h:87
std::enable_if< detail::has_destroy_v< P, T * >||detail::has_destroy_v< F, T * >, void >::type destroy(T *p) noexcept((!detail::has_destroy_v< P, T * >||detail::has_nothrow_destroy_v< P, T * >) &&(!detail::has_destroy_v< F, T * >||detail::has_nothrow_destroy_v< F, T * >) &&std::is_nothrow_destructible_v< T >)
Definition: fallback.h:155
std::enable_if< detail::has_max_size_v< Primary > &&detail::has_max_size_v< Fallback >, size_type >::type max_size() const noexcept(detail::has_nothrow_max_size_v< Primary > &&detail::has_nothrow_max_size_v< Fallback >)
Definition: fallback.h:187
std::enable_if< detail::has_owns_v< Primary > &&detail::has_owns_v< Fallback >, bool >::type owns(void *p) const noexcept(detail::has_nothrow_owns_v< Primary > &&detail::has_nothrow_owns_v< Fallback >)
Definition: fallback.h:195
void deallocate(void *p, size_t n) noexcept(detail::has_nothrow_deallocate_v< P > &&detail::has_nothrow_deallocate_v< F >)
Definition: fallback.h:109
detail::get_size_type_t< P > size_type
Definition: fallback.h:25
std::enable_if< detail::has_construct_v< P, T *, Args... >||detail::has_construct_v< F, T *, Args... >, void >::type construct(T *p, Args &&... args) noexcept((!detail::has_construct_v< P, T *, Args... >||detail::has_nothrow_construct_v< P, T *, Args... >) &&(!detail::has_construct_v< F, T *, Args... >||detail::has_nothrow_construct_v< F, T *, Args... >) &&std::is_nothrow_constructible_v< T, Args... >)
Definition: fallback.h:125
fallback & operator=(const fallback &)=default
fallback(Primary &&primary) noexcept(std::is_nothrow_constructible_v< P, Primary > &&std::is_nothrow_default_constructible_v< F >)
Constructor for forwarding a single argument to the primary allocator.
Definition: fallback.h:39
#define KTL_EMPTY_BASE
Definition: empty_base.h:6
constexpr bool has_construct_v
Definition: meta.h:41
typename get_size_type< Alloc, void >::type get_size_type_t
Definition: meta.h:31
constexpr bool has_nothrow_max_size_v
Definition: meta.h:122
Definition: cascading.h:15