chromium/third_party/libc++/src/include/__memory/allocator_traits.h

// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H
#define _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H

#include <__config>
#include <__memory/construct_at.h>
#include <__memory/pointer_traits.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/is_constructible.h>
#include <__type_traits/is_empty.h>
#include <__type_traits/is_same.h>
#include <__type_traits/make_unsigned.h>
#include <__type_traits/remove_reference.h>
#include <__type_traits/void_t.h>
#include <__utility/declval.h>
#include <__utility/forward.h>
#include <cstddef>
#include <limits>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
#  pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

#define _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX

// __pointer
template <class _Tp,
          class _Alloc,
          class _RawAlloc = __libcpp_remove_reference_t<_Alloc>,
          bool            = __has_pointer<_RawAlloc>::value>
struct __pointer {};
__pointer<_Tp, _Alloc, _RawAlloc, false>;

// __const_pointer
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Tp, class _Ptr, class _Alloc, bool = __has_const_pointer<_Alloc>::value>
struct __const_pointer {};
__const_pointer<_Tp, _Ptr, _Alloc, false>;

// __void_pointer
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Ptr, class _Alloc, bool = __has_void_pointer<_Alloc>::value>
struct __void_pointer {};
__void_pointer<_Ptr, _Alloc, false>;

// __const_void_pointer
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Ptr, class _Alloc, bool = __has_const_void_pointer<_Alloc>::value>
struct __const_void_pointer {};
__const_void_pointer<_Ptr, _Alloc, false>;

// __size_type
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Alloc, class _DiffType, bool = __has_size_type<_Alloc>::value>
struct __size_type : make_unsigned<_DiffType> {};
__size_type<_Alloc, _DiffType, true>;

// __alloc_traits_difference_type
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Alloc, class _Ptr, bool = __has_alloc_traits_difference_type<_Alloc>::value>
struct __alloc_traits_difference_type {};
__alloc_traits_difference_type<_Alloc, _Ptr, true>;

// __propagate_on_container_copy_assignment
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Alloc, bool = __has_propagate_on_container_copy_assignment<_Alloc>::value>
struct __propagate_on_container_copy_assignment : false_type {};
__propagate_on_container_copy_assignment<_Alloc, true>;

// __propagate_on_container_move_assignment
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Alloc, bool = __has_propagate_on_container_move_assignment<_Alloc>::value>
struct __propagate_on_container_move_assignment : false_type {};
__propagate_on_container_move_assignment<_Alloc, true>;

// __propagate_on_container_swap
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Alloc, bool = __has_propagate_on_container_swap<_Alloc>::value>
struct __propagate_on_container_swap : false_type {};
__propagate_on_container_swap<_Alloc, true>;

// __is_always_equal
_LIBCPP_ALLOCATOR_TRAITS_HAS_XXX;
template <class _Alloc, bool = __has_is_always_equal<_Alloc>::value>
struct __is_always_equal : is_empty<_Alloc> {};
__is_always_equal<_Alloc, true>;

// __allocator_traits_rebind
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
template <class _Tp, class _Up, class = void>
struct __has_rebind_other : false_type {};
__has_rebind_other<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>::other>>;

template <class _Tp, class _Up, bool = __has_rebind_other<_Tp, _Up>::value>
struct __allocator_traits_rebind {};
__allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, true>;
__allocator_traits_rebind<_Alloc<_Tp, _Args...>, _Up, false>;
_LIBCPP_SUPPRESS_DEPRECATED_POP

__allocator_traits_rebind_t;

_LIBCPP_SUPPRESS_DEPRECATED_PUSH

// __has_allocate_hint
template <class _Alloc, class _SizeType, class _ConstVoidPtr, class = void>
struct __has_allocate_hint : false_type {};

__has_allocate_hint<_Alloc, _SizeType, _ConstVoidPtr, decltype((void)std::declval<_Alloc>().allocate(std::declval<_SizeType>(), std::declval<_ConstVoidPtr>()))>;

// __has_construct
template <class, class _Alloc, class... _Args>
struct __has_construct_impl : false_type {};

__has_construct_impl<decltype((void)std::declval<_Alloc>().construct(std::declval<_Args>()...)), _Alloc, _Args...>;

template <class _Alloc, class... _Args>
struct __has_construct : __has_construct_impl<void, _Alloc, _Args...> {};

// __has_destroy
template <class _Alloc, class _Pointer, class = void>
struct __has_destroy : false_type {};

__has_destroy<_Alloc, _Pointer, decltype((void)std::declval<_Alloc>().destroy(std::declval<_Pointer>()))>;

// __has_max_size
template <class _Alloc, class = void>
struct __has_max_size : false_type {};

__has_max_size<_Alloc, decltype((void)std::declval<_Alloc &>().max_size())>;

// __has_select_on_container_copy_construction
template <class _Alloc, class = void>
struct __has_select_on_container_copy_construction : false_type {};

__has_select_on_container_copy_construction<_Alloc, decltype((void)std::declval<_Alloc>().select_on_container_copy_construction())>;

_LIBCPP_SUPPRESS_DEPRECATED_POP

#if _LIBCPP_STD_VER >= 23

template <class _Pointer, class _SizeType = size_t>
struct allocation_result {
  _Pointer ptr;
  _SizeType count;
};
_LIBCPP_CTAD_SUPPORTED_FOR_TYPE(allocation_result);

#endif // _LIBCPP_STD_VER

template <class _Alloc>
struct _LIBCPP_TEMPLATE_VIS allocator_traits {};

#ifndef _LIBCPP_CXX03_LANG
__rebind_alloc;
#else
template <class _Traits, class _Tp>
using __rebind_alloc = typename _Traits::template rebind_alloc<_Tp>::other;
#endif

template <class _Alloc>
struct __check_valid_allocator : true_type {};

// __is_default_allocator
template <class _Tp>
struct __is_default_allocator : false_type {};

template <class>
class allocator;

__is_default_allocator<allocator<_Tp>>;

// __is_cpp17_move_insertable
template <class _Alloc, class = void>
struct __is_cpp17_move_insertable : is_move_constructible<typename _Alloc::value_type> {};

__is_cpp17_move_insertable<_Alloc, __enable_if_t<!__is_default_allocator<_Alloc>::value && __has_construct<_Alloc, typename _Alloc::value_type *, typename _Alloc::value_type &&>::value>>;

// __is_cpp17_copy_insertable
template <class _Alloc, class = void>
struct __is_cpp17_copy_insertable
    : integral_constant<bool,
                        is_copy_constructible<typename _Alloc::value_type>::value &&
                            __is_cpp17_move_insertable<_Alloc>::value > {};

__is_cpp17_copy_insertable<_Alloc, __enable_if_t<!__is_default_allocator<_Alloc>::value && __has_construct<_Alloc, typename _Alloc::value_type *, const typename _Alloc::value_type &>::value>>;

#undef _LIBCPP_ALLOCATOR_TRAITS_HAS_XXX

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___MEMORY_ALLOCATOR_TRAITS_H