30 #ifndef BIT_MEMORY_CONCEPTS_ALLOCATOR_HPP 31 #define BIT_MEMORY_CONCEPTS_ALLOCATOR_HPP 33 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 35 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 37 #include "detail/identity.hpp" 38 #include "detail/void_t.hpp" 39 #include "detail/allocator_utilities.hpp" 41 #include "../utilities/allocator_info.hpp" 44 #include <type_traits> 188 #if __cplusplus >= 202000L 191 concept Allocator = requires( T a,
192 allocator_pointer_t<T> p,
193 allocator_size_type_t<T> size,
194 allocator_size_type_t<T> align )
196 { a.try_allocate( size, align ) } -> allocator_pointer_t<T>;
197 { a.deallocate( p, size ) };
207 template<
typename T,
typename =
void>
208 struct allocator_has_allocate_impl : std::false_type{};
211 struct allocator_has_allocate_impl<T,
212 void_t<decltype(
std::declval<allocator_pointer_t<T>&>()
213 = std::declval<T&>().allocate( std::declval<allocator_size_type_t<T>>(),
214 std::declval<allocator_size_type_t<T>>() ))
216 > : std::true_type{};
220 template<
typename T,
typename =
void>
221 struct allocator_has_allocate_hint_impl : std::false_type{};
224 struct allocator_has_allocate_hint_impl<T,
225 void_t<decltype(
std::declval<allocator_pointer_t<T>&>()
226 = std::declval<T&>().allocate( std::declval<allocator_const_pointer_t<T>>(),
227 std::declval<allocator_size_type_t<T>>(),
228 std::declval<allocator_size_type_t<T>>() ))
230 > : std::true_type{};
234 template<
typename T,
typename =
void>
235 struct allocator_has_try_allocate_impl : std::false_type{};
238 struct allocator_has_try_allocate_impl<T,
239 void_t<decltype(
std::declval<allocator_pointer_t<T>&>()
240 = std::declval<T&>().try_allocate( std::declval<allocator_size_type_t<T>>(),
241 std::declval<allocator_size_type_t<T>>() ))
243 > : std::true_type{};
247 template<
typename T,
typename =
void>
248 struct allocator_has_try_allocate_hint_impl : std::false_type{};
251 struct allocator_has_try_allocate_hint_impl<T,
252 void_t<decltype(
std::declval<allocator_pointer_t<T>&>()
253 = std::declval<T&>().try_allocate( std::declval<allocator_const_pointer_t<T>>(),
254 std::declval<allocator_size_type_t<T>>(),
255 std::declval<allocator_size_type_t<T>>() ))
257 > : std::true_type{};
261 template<
typename...>
struct allocator_type_list;
265 template<
typename T,
typename U,
typename List,
typename =
void>
266 struct allocator_has_construct_impl : std::false_type{};
268 template<
typename T,
typename U,
typename...Args>
269 struct allocator_has_construct_impl<T,U,allocator_type_list<Args...>,
271 decltype(
std::declval<T&>().template construct<U>( std::declval<void*>(), std::declval<Args>()... ) )
273 > : std::true_type{};
277 template<
typename T,
typename U,
typename List,
typename =
void>
278 struct allocator_has_make_impl : std::false_type{};
280 template<
typename T,
typename U,
typename...Args>
281 struct allocator_has_make_impl<T,U,allocator_type_list<Args...>,
283 decltype(
std::declval<T&>().template make<U>( std::declval<Args>()... ) )
285 > : std::true_type{};
289 template<
typename T,
typename U,
typename List,
typename =
void>
290 struct allocator_has_make_array_impl : std::false_type{};
292 template<
typename T,
typename U,
typename...Args>
293 struct allocator_has_make_array_impl<T,U,allocator_type_list<Args...>,
295 decltype(
std::declval<T&>().template make_array<U>( std::declval<Args>()... ) )
297 > : std::true_type{};
301 template<
typename T,
typename =
void>
302 struct allocator_has_deallocate_impl : std::false_type{};
305 struct allocator_has_deallocate_impl<T,
306 void_t<decltype(
std::declval<T&>().deallocate( std::declval<allocator_pointer_t<T>&>(),
307 std::declval<allocator_size_type_t<T>>() ))
309 > : std::true_type{};
313 template<
typename T,
typename =
void>
314 struct allocator_has_deallocate_all_impl : std::false_type{};
317 struct allocator_has_deallocate_all_impl<T,
318 void_t<decltype(
std::declval<T&>().deallocate_all())>
319 > : std::true_type{};
323 template<
typename T,
typename,
typename =
void>
324 struct allocator_has_destroy_impl : std::false_type{};
326 template<
typename T,
typename U>
327 struct allocator_has_destroy_impl<T,U,
329 decltype(
std::declval<T&>().dispose( std::declval<U>() ) )
331 > : std::true_type{};
335 template<
typename T,
typename,
typename =
void>
336 struct allocator_has_dispose_impl : std::false_type{};
338 template<
typename T,
typename U>
339 struct allocator_has_dispose_impl<T,U,
341 decltype(
std::declval<T&>().dispose( std::declval<U&>() ) )
343 > : std::true_type{};
347 template<
typename T,
typename,
typename =
void>
348 struct allocator_has_dispose_array_impl : std::false_type{};
350 template<
typename T,
typename U>
351 struct allocator_has_dispose_array_impl<T,U,
353 decltype(
std::declval<T&>().dispose_array( std::declval<U&>(), std::declval<allocator_size_type_t<T>>() ) )
355 > : std::true_type{};
359 template<
typename T,
typename =
void>
360 struct allocator_has_recommended_allocation_size_impl : std::false_type{};
363 struct allocator_has_recommended_allocation_size_impl<T,
364 void_t<decltype(
std::declval<allocator_size_type_t<T>&>()
365 = std::declval<const T&>().recommended_allocation_size( std::declval<allocator_size_type_t<T>>() ))
367 > : std::true_type{};
371 template<
typename T,
typename =
void>
372 struct allocator_has_owns_impl : std::false_type{};
375 struct allocator_has_owns_impl<T,
376 void_t<decltype(
std::declval<bool&>()
377 = std::declval<const T&>().owns( std::declval<allocator_const_pointer_t<T>>() ))
379 > : std::true_type{};
383 template<
typename T,
typename =
void>
384 struct allocator_has_info_impl : std::false_type{};
387 struct allocator_has_info_impl<T,
388 void_t<decltype(
std::declval<allocator_info>() = std::declval<const T&>().info() )>
389 > : std::true_type{};
393 template<
typename T,
typename =
void>
394 struct allocator_has_is_unbounded_impl : std::false_type{};
397 struct allocator_has_is_unbounded_impl<T,
398 void_t<decltype(
std::declval<bool&>()
399 = std::declval<const T&>().is_unbounded())
401 > : std::true_type{};
405 template<
typename T,
typename =
void>
406 struct allocator_has_max_size_impl : std::false_type{};
409 struct allocator_has_max_size_impl<T,
410 void_t<decltype(
std::declval<allocator_size_type_t<T>&>()
411 = std::declval<const T&>().max_size())
413 > : std::true_type{};
417 template<
typename T,
typename =
void>
418 struct allocator_has_min_size_impl : std::false_type{};
421 struct allocator_has_min_size_impl<T,
422 void_t<decltype(
std::declval<allocator_size_type_t<T>&>()
423 = std::declval<const T&>().min_size())
425 > : std::true_type{};
429 template<
typename T,
typename =
void>
430 struct allocator_default_alignment_impl
431 : std::integral_constant<allocator_size_type_t<T>,1>{};
434 struct allocator_default_alignment_impl<T,
435 void_t<decltype(T::default_alignment)>>
436 : T::default_alignment{};
440 template<
typename T,
typename =
void>
441 struct allocator_max_alignment_impl
442 : std::integral_constant<allocator_size_type_t<T>,alignof(std::max_align_t)>{};
445 struct allocator_max_alignment_impl<T,
446 void_t<decltype(T::max_alignment)>>
447 : std::integral_constant<allocator_size_type_t<T>,alignof(std::max_align_t)>{};
451 template<
typename T,
typename =
void>
452 struct allocator_has_expand : std::false_type{};
455 struct allocator_has_expand<T,
456 void_t<decltype(
std::declval<bool&>()
457 = std::declval<T&>().expand( std::declval<allocator_pointer_t<T>&>(),
458 std::declval<allocator_size_type_t<T>>() ))
460 > : std::true_type{};
472 : detail::allocator_has_try_allocate_hint_impl<T>{};
479 constexpr
bool allocator_has_try_allocate_hint_v
491 : detail::allocator_has_allocate_impl<T>{};
498 constexpr
bool allocator_has_allocate_v
510 : detail::allocator_has_allocate_hint_impl<T>{};
517 constexpr
bool allocator_has_allocate_hint_v
527 template<
typename T,
typename U,
typename...Args>
529 : detail::allocator_has_construct_impl<T,U,detail::allocator_type_list<Args...>>{};
535 template<
typename T,
typename U,
typename...Args>
536 constexpr
bool allocator_has_construct_v
546 template<
typename T,
typename U,
typename...Args>
548 : detail::allocator_has_make_impl<T,U,detail::allocator_type_list<Args...>>{};
554 template<
typename T,
typename U,
typename...Args>
555 constexpr
bool allocator_has_make_v
565 template<
typename T,
typename U,
typename...Args>
567 : detail::allocator_has_make_array_impl<T,U,detail::allocator_type_list<Args...>>{};
573 template<
typename T,
typename U,
typename...Args>
574 constexpr
bool allocator_has_make_array_v
587 : detail::allocator_has_deallocate_all_impl<T>{};
604 template<
typename T,
typename U>
606 : detail::allocator_has_destroy_impl<T,U>{};
612 template<
typename T,
typename U>
613 constexpr
bool allocator_has_destroy_v
624 template<
typename T,
typename U>
626 : detail::allocator_has_dispose_impl<T,U>{};
632 template<
typename T,
typename U>
633 constexpr
bool allocator_has_dispose_v
644 template<
typename T,
typename U>
646 : detail::allocator_has_dispose_array_impl<T,U>{};
652 template<
typename T,
typename U>
653 constexpr
bool allocator_has_dispose_array_v
666 : detail::allocator_has_recommended_allocation_size_impl<T>{};
673 constexpr
bool allocator_has_recommended_allocation_size_v
685 : detail::allocator_has_owns_impl<T>{};
703 : detail::allocator_has_info_impl<T>{};
721 : detail::allocator_has_is_unbounded_impl<T>{};
739 : detail::allocator_has_max_size_impl<T>{};
757 : detail::allocator_has_min_size_impl<T>{};
775 : detail::allocator_default_alignment_impl<T>{};
793 : detail::allocator_max_alignment_impl<T>{};
812 : detail::allocator_has_expand<T>{};
831 detail::allocator_has_try_allocate_impl<T>::value &&
832 detail::allocator_has_deallocate_impl<T>::value
Type-trait to determine whether T has a 'dispose' function.
Type-trait to determine whether T has a 'min_size' function.
Type-trait to determine whether T has an 'info' function.
Type-trait to determine whether T has a 'max_size' function.
Type-trait to determine whether T has a 'deallocate_all' function.
Type-trait to determine the default alignment of the given T.
Type-trait to determine whether T has a 'make_array' function.
Type-trait to determine whether T satisfies the minimum requirements to be an Allocator.
Type-trait to determine whether T has an 'allocate' function.
Type-trait to determine whether T has a 'try_allocate' function that accepts a hint.
Type-trait to determine the maximum alignment of the given T.
Type-trait to determine whether T has a 'destroy' function.
Type-trait to determine whether T has a 'construct' function.
Type-trait to determine whether T has a 'dispose_array' function.
Type trait to determine whether the allocator has the expand function.
Type-trait to determine whether T has a 'make' function.
Type-trait to determine whether T has an 'allocate' function.
Type-trait to determine whether T has a 'recommended_allocation_size' function.
Type-trait to determine whether T has an 'owns' function.
Type-trait to determine whether T has a 'is_unbounded' function.