File Index Symbol Index

// xmemory0 internal header
#pragma once
#ifndef _XMEMORY0_
#define _XMEMORY0_
#ifndef RC_INVOKED #include <cstdint> /* for uintptr_t */
#include <cstdlib> #include <limits>
#include <new> #include <xutility>
_STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new
// FUNCTION TEMPLATE _Get_size_of_n
template
<
size_t
_Ty_size
>
inline
size_t
_Get_size_of_n
(
const
size_t
_Count
) {
// gets the size of _Count copies of a type sized _Ty_size
constexpr
size_t
_Max_possible
=
static_cast
<
size_t
>(-
1
) /
_Ty_size
;
size_t
_Result
=
_Count
*
_Ty_size
;
if
(
_Max_possible
<
_Count
) {
// multiply overflow, try allocating all of memory and assume the
// allocation function will throw bad_alloc
_Result
=
static_cast
<
size_t
>(-
1
); }
return
(
_Result
); }
template
<>
inline
size_t
_Get_size_of_n
<
1
>(
const
size_t
_Count
) {
// gets the size of _Count copies of a type with size 1
return
(
_Count
); }
// VARIABLE TEMPLATE _New_alignof
template
<
class
_Ty
> );
// STRUCT _Default_allocate_traits
struct
_Default_allocate_traits
{ {
return
(::
operator
new
(
_Bytes
)); }
#if _HAS_ALIGNED_NEW
_DECLSPEC_ALLOCATOR static void * _Allocate_aligned(const size_t _Bytes, const size_t _Align)
{
return (::operator new(_Bytes, align_val_t{_Align}));
} #endif /* _HAS_ALIGNED_NEW */
};
constexpr
bool
_Is_pow_2
(
const
size_t
_Value
)
noexcept
{
return
(
_Value
!
=
0
&& (
_Value
& (
_Value
-
1
))
=
=
0
); }
#if defined(_M_IX86) || defined(_M_X64)
constexpr
size_t
_Big_allocation_threshold
=
4096
;
constexpr
size_t
_Big_allocation_alignment
=
32
;
static_assert
(
2
*
sizeof
(
void
*) <=
_Big_allocation_alignment
,
"Big allocation alignment should at least match vector register alignment"
);
static_assert
(
_Is_pow_2
(
_Big_allocation_alignment
),
"Big allocation alignment must be a power of two"
);
#ifdef _DEBUG
constexpr
size_t
_Non_user_size
=
2
*
sizeof
(
void
*) +
_Big_allocation_alignment
-
1
;
#else /* _DEBUG */
constexpr size_t _Non_user_size = sizeof(void *) + _Big_allocation_alignment - 1; #endif /* _DEBUG */
#ifdef _WIN64
constexpr size_t _Big_allocation_sentinel = 0xFAFAFAFAFAFAFAFAULL;
#else /* ^^^ _WIN64 ^^^ // vvv !_WIN64 vvv */
constexpr
size_t
_Big_allocation_sentinel
=
0xFAFAFAFAUL
;
#endif /* _WIN64 */
// FUNCTION _Allocate_manually_vector_aligned
template
<
class
_Traits
>
inline
{
// allocate _Bytes manually aligned to at least _Big_allocation_alignment
size_t
_Block_size
=
_Non_user_size
+
_Bytes
;
if
(
_Block_size
<=
_Bytes
) {
// add overflow, try allocating all of memory and assume the
// allocation function will throw bad_alloc
_Block_size
=
static_cast
<
size_t
>(-
1
); }
const
uintptr_t
_Ptr_container
=
reinterpret_cast
<
uintptr_t
>(
_Traits
::_Allocate(
_Block_size
));
void
*
const
_Ptr
=
reinterpret_cast
<
void
*>((
_Ptr_container
+
_Non_user_size
) & ~(
_Big_allocation_alignment
-
1
));
static_cast
<
uintptr_t
*>(
_Ptr
)[-
1
] =
_Ptr_container
;
#ifdef _DEBUG
static_cast
<
uintptr_t
*>(
_Ptr
)[-
2
] =
_Big_allocation_sentinel
;
#endif /* _DEBUG */
return
(
_Ptr
); }
// FUNCTION TEMPLATE _Adjust_manually_vector_aligned
inline
void
_Adjust_manually_vector_aligned
(
void
*&
_Ptr
,
size_t
&
_Bytes
) {
// adjust parameters from _Allocate_manually_vector_aligned to pass to operator delete
_Bytes
+=
_Non_user_size
;
const
uintptr_t
*
const
_Ptr_user
=
reinterpret_cast
<
uintptr_t
*>(
_Ptr
);
const
uintptr_t
_Ptr_container
=
_Ptr_user
[-
1
];
// If the following asserts, it likely means that we are performing
// an aligned delete on memory coming from an unaligned allocation.
// Extra paranoia on aligned allocation/deallocation; ensure _Ptr_container is
// in range [_Min_back_shift, _Non_user_size]
#ifdef _DEBUG
constexpr
uintptr_t
_Min_back_shift
=
2
*
sizeof
(
void
*);
#else /* ^^^ _DEBUG ^^^ // vvv !_DEBUG vvv */
constexpr uintptr_t _Min_back_shift = sizeof(void *); #endif /* _DEBUG */
const
uintptr_t
_Back_shift
=
reinterpret_cast
<
uintptr_t
>(
_Ptr
) -
_Ptr_container
;
_Ptr
=
reinterpret_cast
<
void
*>(
_Ptr_container
); }
#endif /* defined(_M_IX86) || defined(_M_X64) */
// FUNCTION TEMPLATES _Allocate and _Deallocate
#if _HAS_ALIGNED_NEW
template<size_t _Align,
class _Traits = _Default_allocate_traits,
enable_if_t<(_Align > __STDCPP_DEFAULT_NEW_ALIGNMENT__), int> = 0> inline
_DECLSPEC_ALLOCATOR void *_Allocate(const size_t _Bytes)
{ // allocate _Bytes when _HAS_ALIGNED_NEW && _Align > __STDCPP_DEFAULT_NEW_ALIGNMENT__
if (_Bytes == 0)
{
return (nullptr);
}
size_t _Passed_align = _Align;
#if defined(_M_IX86) || defined(_M_X64)
if (_Bytes >= _Big_allocation_threshold)
{ // boost the alignment of big allocations to help autovectorization
_Passed_align = _Max_value(_Align, _Big_allocation_alignment);
}
#endif /* defined(_M_IX86) || defined(_M_X64) */
return (_Traits::_Allocate_aligned(_Bytes, _Passed_align));
}
template<size_t _Align,
enable_if_t<(_Align > __STDCPP_DEFAULT_NEW_ALIGNMENT__), int> = 0> inline
void _Deallocate(void * _Ptr, const size_t _Bytes)
{ // deallocate storage allocated by _Allocate when _HAS_ALIGNED_NEW && _Align > __STDCPP_DEFAULT_NEW_ALIGNMENT__
size_t _Passed_align = _Align;
#if defined(_M_IX86) || defined(_M_X64)
if (_Bytes >= _Big_allocation_threshold)
{ // boost the alignment of big allocations to help autovectorization
_Passed_align = _Max_value(_Align, _Big_allocation_alignment);
}
#endif /* defined(_M_IX86) || defined(_M_X64) */
::operator delete(_Ptr, _Bytes, align_val_t{_Passed_align});
} #endif /* _HAS_ALIGNED_NEW */
template
<
size_t
_Align
,
class
_Traits
=
_Default_allocate_traits
, {
// allocate _Bytes when !_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__
#if defined(_M_IX86) || defined(_M_X64)
if
(
_Bytes
>=
_Big_allocation_threshold
) {
// boost the alignment of big allocations to help autovectorization
return
(
_Allocate_manually_vector_aligned
<
_Traits
>(
_Bytes
)); }
#endif /* defined(_M_IX86) || defined(_M_X64) */
if
(
_Bytes
!
=
0
) {
return
(
_Traits
::_Allocate(
_Bytes
)); }
return
(
nullptr
); }
template
<
size_t
_Align
,
void
_Deallocate
(
void
*
_Ptr
,
size_t
_Bytes
) {
// deallocate storage allocated by _Allocate when !_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__
#if defined(_M_IX86) || defined(_M_X64)
if
(
_Bytes
>=
_Big_allocation_threshold
) {
// boost the alignment of big allocations to help autovectorization
_Adjust_manually_vector_aligned
(
_Ptr
,
_Bytes
); }
#endif /* defined(_M_IX86) || defined(_M_X64) */
::
operator
delete
(
_Ptr
,
_Bytes
); }
// FUNCTION TEMPLATE _Construct_in_place
template
<
class
_Ty
,
class
...
_Types
>
inline
void
_Construct_in_place
(
_Ty
&
_Obj
,
_Types
&&...
_Args
) {
// invoke True Placement New to initialize the referenced object with _Args...
}
// FUNCTION TEMPLATE _Global_new
template
<
class
_Ty
,
class
...
_Types
>
inline
_Ty
*
_Global_new
(
_Types
&&...
_Args
) {
// acts as "new" while disallowing user overload selection
void
*
const
_Result
=
_Allocate
<
_New_alignof
<
_Ty
>>(
sizeof
(
_Ty
));
_Deallocate
<
_New_alignof
<
_Ty
>>(
_Result
,
sizeof
(
_Ty
));
return
(
static_cast
<
_Ty
*>(
_Result
)); }
// STRUCT TEMPLATE _Get_first_parameter
template
<
class
_Ty
>
struct
_Get_first_parameter
;
template
<
template
<
class
,
class
...>
class
_Ty
,
class
_First
,
class
...
_Rest
>
struct
_Get_first_parameter
<
_Ty
<
_First
,
_Rest
...>> {
// given _Ty<_First, _Rest...>, extract _First
using
type
=
_First
; };
// STRUCT TEMPLATE _Replace_first_parameter
template
<
class
_Newfirst
,
class
_Ty
>
struct
_Replace_first_parameter
;
template
<
class
_Newfirst
,
template
<
class
,
class
...>
class
_Ty
,
class
_First
,
class
...
_Rest
>
struct
_Replace_first_parameter
<
_Newfirst
,
_Ty
<
_First
,
_Rest
...>> {
// given _Ty<_First, _Rest...>, replace _First
using
type
=
_Ty
<
_Newfirst
,
_Rest
...>; };
// STRUCT TEMPLATE _Get_element_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_element_type
{
// provide fallback
using
type
=
typename
_Get_first_parameter
<
_Ty
>::
type
; };
template
<
class
_Ty
>
struct
_Get_element_type
<
_Ty
,
void_t
<
typename
_Ty
::element_type>> {
// get _Ty::element_type
using
type
=
typename
_Ty
::element_type; };
// STRUCT TEMPLATE _Get_ptr_difference_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_ptr_difference_type
{
// provide fallback
using
type
=
ptrdiff_t
; };
template
<
class
_Ty
>
struct
_Get_ptr_difference_type
<
_Ty
,
void_t
<
typename
_Ty
::difference_type>> {
// get _Ty::difference_type
using
type
=
typename
_Ty
::difference_type; };
// STRUCT TEMPLATE _Get_rebind_alias
template
<
class
_Ty
,
class
_Other
,
class
=
void
>
struct
_Get_rebind_alias
{
// provide fallback
using
type
=
typename
_Replace_first_parameter
<
_Other
,
_Ty
>::
type
; };
template
<
class
_Ty
,
class
_Other
>
struct
_Get_rebind_alias
<
_Ty
,
_Other
,
void_t
<
typename
_Ty
::
template
rebind<
_Other
>>> {
// get _Ty::rebind<_Other>
using
type
=
typename
_Ty
::
template
rebind<
_Other
>; };
// STRUCT TEMPLATE pointer_traits
template
<
class
_Ty
>
struct
pointer_traits
{
// defines traits for arbitrary pointers
using
element_type
=
typename
_Get_element_type
<
_Ty
>::
type
;
using
pointer
=
_Ty
;
using
difference_type
=
typename
_Get_ptr_difference_type
<
_Ty
>::
type
;
template
<
class
_Other
>
using
rebind
=
typename
_Get_rebind_alias
<
_Ty
,
_Other
>::
type
;
using
_Reftype
=
conditional_t
<
is_void_v
<
element_type
>,
char
&,
add_lvalue_reference_t
<
element_type
>>; {
// convert raw reference to pointer
return
(
_Ty
::pointer_to(
_Val
)); } };
template
<
class
_Ty
>
struct
pointer_traits
<
_Ty
*> {
// defines traits for raw pointers
using
element_type
=
_Ty
;
using
pointer
=
_Ty
*;
using
difference_type
=
ptrdiff_t
;
template
<
class
_Other
>
using
rebind
=
_Other
*;
using
_Reftype
=
conditional_t
<
is_void_v
<
_Ty
>,
char
&,
add_lvalue_reference_t
<
_Ty
>>; {
// convert raw reference to pointer
} };
// ALIAS TEMPLATE _Rebind_pointer_t
template
<
class
_Ptr
,
class
_Ty
>
using
_Rebind_pointer_t
=
typename
pointer_traits
<
_Ptr
>::
template
rebind
<
_Ty
>;
// FUNCTION TEMPLATE _Refancy
template
<
class
_Pointer
,
enable_if_t
<!
is_pointer_v
<
_Pointer
>,
int
> =
0
>
inline
_Pointer
_Refancy
(
typename
pointer_traits
<
_Pointer
>::
element_type
*
_Ptr
) {
// transform a plain pointer into a fancy pointer
return
(
pointer_traits
<
_Pointer
>::
pointer_to
(*
_Ptr
)); }
template
<
class
_Pointer
,
enable_if_t
<
is_pointer_v
<
_Pointer
>,
int
> =
0
>
inline
_Pointer
_Refancy
(
_Pointer
_Ptr
) {
// do nothing for plain pointers
return
(
_Ptr
); }
// FUNCTION TEMPLATE _Destroy_in_place
template
<
class
_Ty
>
inline
void
_Destroy_in_place
(
_Ty
&
_Obj
)
noexcept
{
// destroy the referenced object
_Obj
.~_Ty(); }
// FUNCTION TEMPLATE _Const_cast
template
<
class
_Ptrty
>
inline
auto
_Const_cast
(
_Ptrty
_Ptr
) {
// remove constness from a fancy pointer
using
_Elem
=
typename
pointer_traits
<
_Ptrty
>::
element_type
;
using
_Modifiable
=
remove_const_t
<
_Elem
>;
using
_Dest
=
typename
pointer_traits
<
_Ptrty
>::
template
rebind
<
_Modifiable
>;
return
(
pointer_traits
<
_Dest
>::
pointer_to
(
const_cast
<
_Modifiable
&>(*
_Ptr
))); }
template
<
class
_Ty
>
inline
auto
_Const_cast
(
_Ty
*
_Ptr
) {
// remove constness from a plain pointer
return
(
const_cast
<
remove_const_t
<
_Ty
> *>(
_Ptr
)); }
// STRUCT TEMPLATE _Get_pointer_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_pointer_type
{
// provide fallback
using
type
=
typename
_Ty
::value_type *; }; #pragma warning(push)
template
<
class
_Ty
>
struct
_Get_pointer_type
<
_Ty
,
void_t
<
typename
_Ty
::pointer>> {
// get _Ty::pointer
using
type
=
typename
_Ty
::pointer; }; #pragma warning(pop)
// STRUCT TEMPLATE _Get_const_pointer_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_const_pointer_type
{
// provide fallback
using
_Ptrty
=
typename
_Get_pointer_type
<
_Ty
>::
type
;
using
_Valty
=
typename
_Ty
::value_type;
using
type
=
typename
pointer_traits
<
_Ptrty
>::
template
rebind
<
const
_Valty
>; }; #pragma warning(push)
template
<
class
_Ty
>
struct
_Get_const_pointer_type
<
_Ty
,
void_t
<
typename
_Ty
::const_pointer>> {
// get _Ty::const_pointer
using
type
=
typename
_Ty
::const_pointer; }; #pragma warning(pop)
// STRUCT TEMPLATE _Get_void_pointer_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_void_pointer_type
{
// provide fallback
using
_Ptrty
=
typename
_Get_pointer_type
<
_Ty
>::
type
;
using
type
=
typename
pointer_traits
<
_Ptrty
>::
template
rebind
<
void
>; };
template
<
class
_Ty
>
struct
_Get_void_pointer_type
<
_Ty
,
void_t
<
typename
_Ty
::void_pointer>> {
// get _Ty::void_pointer
using
type
=
typename
_Ty
::void_pointer; };
// STRUCT TEMPLATE _Get_const_void_pointer_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_const_void_pointer_type
{
// provide fallback
using
_Ptrty
=
typename
_Get_pointer_type
<
_Ty
>::
type
;
using
type
=
typename
pointer_traits
<
_Ptrty
>::
template
rebind
<
const
void
>; };
template
<
class
_Ty
>
struct
_Get_const_void_pointer_type
<
_Ty
,
void_t
<
typename
_Ty
::const_void_pointer>> {
// get _Ty::const_void_pointer
using
type
=
typename
_Ty
::const_void_pointer; };
// STRUCT TEMPLATE _Get_difference_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_difference_type
{
// provide fallback
using
_Ptrty
=
typename
_Get_pointer_type
<
_Ty
>::
type
;
using
type
=
typename
pointer_traits
<
_Ptrty
>::
difference_type
; }; #pragma warning(push)
template
<
class
_Ty
>
struct
_Get_difference_type
<
_Ty
,
void_t
<
typename
_Ty
::difference_type>> {
// get _Ty::difference_type
using
type
=
typename
_Ty
::difference_type; }; #pragma warning(pop)
// STRUCT TEMPLATE _Get_size_type
template
<
class
_Ty
,
class
=
void
>
struct
_Get_size_type
{
// provide fallback
using
type
=
make_unsigned_t
<
typename
_Get_difference_type
<
_Ty
>::
type
>; }; #pragma warning(push)
template
<
class
_Ty
>
struct
_Get_size_type
<
_Ty
,
void_t
<
typename
_Ty
::size_type>> {
// get _Ty::size_type
using
type
=
typename
_Ty
::size_type; }; #pragma warning(pop)
// STRUCT TEMPLATE _Get_propagate_on_container_copy
template
<
class
_Ty
,
class
=
void
>
struct
_Get_propagate_on_container_copy
{
// provide fallback
using
type
=
false_type
; };
template
<
class
_Ty
>
struct
_Get_propagate_on_container_copy
<
_Ty
,
void_t
<
typename
_Ty
::propagate_on_container_copy_assignment>> {
// get _Ty::propagate_on_container_copy_assignment
using
type
=
typename
_Ty
::propagate_on_container_copy_assignment; };
// STRUCT TEMPLATE _Get_propagate_on_container_move
template
<
class
_Ty
,
class
=
void
>
struct
_Get_propagate_on_container_move
{
// provide fallback
using
type
=
false_type
; };
template
<
class
_Ty
>
struct
_Get_propagate_on_container_move
<
_Ty
,
void_t
<
typename
_Ty
::propagate_on_container_move_assignment>> {
// get _Ty::propagate_on_container_move_assignment
using
type
=
typename
_Ty
::propagate_on_container_move_assignment; };
// STRUCT TEMPLATE _Get_propagate_on_container_swap
template
<
class
_Ty
,
class
=
void
>
struct
_Get_propagate_on_container_swap
{
// provide fallback
using
type
=
false_type
; };
template
<
class
_Ty
>
struct
_Get_propagate_on_container_swap
<
_Ty
,
void_t
<
typename
_Ty
::propagate_on_container_swap>> {
// get _Ty::propagate_on_container_swap
using
type
=
typename
_Ty
::propagate_on_container_swap; };
// STRUCT TEMPLATE _Get_is_always_equal
template
<
class
_Ty
,
class
=
void
>
struct
_Get_is_always_equal
{
// provide fallback
using
type
=
typename
is_empty
<
_Ty
>::
type
; };
template
<
class
_Ty
>
struct
_Get_is_always_equal
<
_Ty
,
void_t
<
typename
_Ty
::is_always_equal>> {
// get _Ty::is_always_equal
using
type
=
typename
_Ty
::is_always_equal; };
// STRUCT TEMPLATE _Get_rebind_type
template
<
class
_Ty
,
class
_Other
,
class
=
void
>
struct
_Get_rebind_type
{
// provide fallback
using
type
=
typename
_Replace_first_parameter
<
_Other
,
_Ty
>::
type
; }; #pragma warning(push)
template
<
class
_Ty
,
class
_Other
>
struct
_Get_rebind_type
<
_Ty
,
_Other
,
void_t
<
typename
_Ty
::
template
rebind<
_Other
>::other>> {
// get _Ty::rebind<_Other>::other
using
type
=
typename
_Ty
::
template
rebind<
_Other
>::other; }; #pragma warning(pop)
// STRUCT TEMPLATE _Is_default_allocator
template
<
class
_Ty
>
class
allocator
;
template
<
class
_Alloc
,
class
=
void
>
struct
_Is_default_allocator
:
false_type
{
// tests whether _Alloc is non-specialized default allocator (N4659 23.10.9 [default.allocator])
};
template
<
class
_Ty
>
struct
_Is_default_allocator
<
allocator
<
_Ty
>,
typename
allocator
<
_Ty
>::_Not_user_specialized> :
true_type
{
// tests whether _Alloc is non-specialized default allocator (N4659 23.10.9 [default.allocator])
};
// ALIAS TEMPLATES _Uses_default_construct AND _Uses_default_construct_t
template
<
class
_Void
,
class
...
_Types
>
struct
_Has_no_alloc_construct
:
true_type
{
// determines whether _Alloc has no construct
}; #pragma warning(push)
template
<
class
_Alloc
,
class
_Ptr
,
class
...
_Args
>
struct
_Has_no_alloc_construct
<
void_t
<
_Alloc
,
_Ptr
,
_Args
...> :
false_type
{
// determines whether _Alloc has no construct
}; #pragma warning(pop)
template
<
class
_Alloc
,
class
_Ptr
,
class
...
_Args
>
using
_Uses_default_construct
=
disjunction
<
_Is_default_allocator
<
_Alloc
>,
_Has_no_alloc_construct
<
void
,
_Alloc
,
_Ptr
,
_Args
...>>;
template
<
class
_Alloc
,
class
_Ptr
,
class
...
_Args
>
using
_Uses_default_construct_t
=
typename
_Uses_default_construct
<
_Alloc
,
_Ptr
,
_Args
...>::
type
;
// ALIAS TEMPLATE _Uses_default_destroy AND _Uses_default_destroy_t
template
<
class
_Alloc
,
class
_Ptr
,
class
=
void
>
struct
_Has_no_alloc_destroy
:
true_type
{
// determines whether _Alloc has no destroy
}; #pragma warning(push)
template
<
class
_Alloc
,
class
_Ptr
> :
false_type
{
// determines whether _Alloc has no destroy
}; #pragma warning(pop)
template
<
class
_Alloc
,
class
_Ptr
>
using
_Uses_default_destroy
=
disjunction
<
_Is_default_allocator
<
_Alloc
>,
_Has_no_alloc_destroy
<
_Alloc
,
_Ptr
>>;
template
<
class
_Alloc
,
class
_Ptr
>
using
_Uses_default_destroy_t
=
typename
_Uses_default_destroy
<
_Alloc
,
_Ptr
>::
type
;
// STRUCT TEMPLATE _Has_allocate_hint
template
<
class
_Alloc
,
class
_Size_type
,
class
_Const_void_pointer
,
class
=
void
>
struct
_Has_allocate_hint
:
false_type
{
// determines whether _Alloc has allocate(n, hint)
}; #pragma warning(push)
template
<
class
_Alloc
,
class
_Size_type
,
class
_Const_void_pointer
>
struct
_Has_allocate_hint
<
_Alloc
,
_Size_type
,
_Const_void_pointer
,
void_t
< :
true_type
{
// determines whether _Alloc has allocate(n, hint)
}; #pragma warning(pop)
// STRUCT TEMPLATE _Has_max_size
template
<
class
_Alloc
,
class
=
void
>
struct
_Has_max_size
:
false_type
{
// determines whether _Alloc has max_size()
}; #pragma warning(push)
template
<
class
_Alloc
> :
true_type
{
// determines whether _Alloc has max_size()
}; #pragma warning(pop)
// STRUCT TEMPLATE _Has_select_on_container_copy_construction
template
<
class
_Alloc
,
class
=
void
>
struct
_Has_select_on_container_copy_construction
:
false_type
{
// determines whether _Alloc has select_on_container_copy_construction()
};
template
<
class
_Alloc
>
struct
_Has_select_on_container_copy_construction
<
_Alloc
,
void_t
< :
true_type
{
// determines whether _Alloc has select_on_container_copy_construction()
};
// STRUCT TEMPLATE allocator_traits
template
<
class
_Alloc
>
struct
allocator_traits
; #pragma warning(push)
template
<
class
_Alloc
>
struct
_Normal_allocator_traits
{
// defines traits for allocators
using
allocator_type
=
_Alloc
;
using
value_type
=
typename
_Alloc
::value_type;
using
pointer
=
typename
_Get_pointer_type
<
_Alloc
>::
type
;
using
const_pointer
=
typename
_Get_const_pointer_type
<
_Alloc
>::
type
;
using
void_pointer
=
typename
_Get_void_pointer_type
<
_Alloc
>::
type
;
using
const_void_pointer
=
typename
_Get_const_void_pointer_type
<
_Alloc
>::
type
;
using
size_type
=
typename
_Get_size_type
<
_Alloc
>::
type
;
using
difference_type
=
typename
_Get_difference_type
<
_Alloc
>::
type
;
using
propagate_on_container_copy_assignment
=
typename
_Get_propagate_on_container_copy
<
_Alloc
>::
type
;
using
propagate_on_container_move_assignment
=
typename
_Get_propagate_on_container_move
<
_Alloc
>::
type
;
using
propagate_on_container_swap
=
typename
_Get_propagate_on_container_swap
<
_Alloc
>::
type
;
using
is_always_equal
=
typename
_Get_is_always_equal
<
_Alloc
>::
type
;
template
<
class
_Other
>
using
rebind_alloc
=
typename
_Get_rebind_type
<
_Alloc
,
_Other
>::
type
;
template
<
class
_Other
>
using
rebind_traits
=
allocator_traits
<
rebind_alloc
<
_Other
>>; {
// allocate array of _Count elements
return
(
_Al
.allocate(
_Count
)); }
const
const_void_pointer
_Hint
,
true_type
) {
// allocate array of _Count elements, with hint, allocator-supplied version
return
(
_Al
.allocate(
_Count
,
_Hint
)); }
const_void_pointer
,
false_type
) {
// allocate array of _Count elements, with hint, default version
return
(
_Al
.allocate(
_Count
)); }
const
const_void_pointer
_Hint
) {
// allocate array of _Count elements, with hint
return
(
_Allocate1
(
_Al
,
_Count
,
_Hint
,
_Has_allocate_hint
<
_Alloc
,
size_type
,
const_void_pointer
>{})); }
static
void
deallocate
(
_Alloc
&
_Al
,
pointer
_Ptr
,
size_type
_Count
) {
// deallocate _Count elements at _Ptr
_Al
.deallocate(
_Ptr
,
_Count
); }
template
<
class
_Ty
,
class
...
_Types
>
static
void
_Construct1
(
true_type
,
_Alloc
&,
_Ty
*
_Ptr
,
_Types
&&...
_Args
) {
// construct _Ty(_Types...) at _Ptr, default version
}
template
<
class
_Ty
,
class
...
_Types
>
static
void
_Construct1
(
false_type
,
_Alloc
&
_Al
,
_Ty
*
_Ptr
,
_Types
&&...
_Args
) {
// construct _Ty(_Types...) at _Ptr, allocator-supplied version
}
template
<
class
_Ty
,
class
...
_Types
>
static
void
construct
(
_Alloc
&
_Al
,
_Ty
*
_Ptr
,
_Types
&&...
_Args
) {
// construct _Ty(_Types...) at _Ptr
_Construct1
(
_Uses_default_construct_t
<
_Alloc
,
_Ty
*,
_Types
...>(), }
template
<
class
_Ty
>
static
void
_Destroy1
(
_Alloc
&,
_Ty
*
_Ptr
,
true_type
) {
// destroy object at _Ptr, default version
_Ptr
->~_Ty(); }
template
<
class
_Ty
>
static
void
_Destroy1
(
_Alloc
&
_Al
,
_Ty
*
_Ptr
,
false_type
) {
// destroy object at _Ptr, allocator-supplied version
_Al
.destroy(
_Ptr
); }
template
<
class
_Ty
>
static
void
destroy
(
_Alloc
&
_Al
,
_Ty
*
_Ptr
) {
// destroy object at _Ptr
_Destroy1
(
_Al
,
_Ptr
,
_Uses_default_destroy_t
<
_Alloc
,
_Ty
*>()); }
static
size_type
_Max_size1
(
const
_Alloc
&
_Al
,
true_type
)
noexcept
{
// get maximum size, allocator-supplied version
return
(
_Al
.max_size()); }
static
size_type
_Max_size1
(
const
_Alloc
&,
false_type
)
noexcept
{
// get maximum size, default version
return
((
numeric_limits
<
size_type
>::
max
)() /
sizeof
(
value_type
)); } {
// get maximum size
return
(
_Max_size1
(
_Al
,
_Has_max_size
<
_Alloc
>{})); }
static
_Alloc
_Select_on_container_copy_construction1
(
const
_Alloc
&
_Al
,
true_type
) {
// get allocator to use, allocator-supplied version
return
(
_Al
.select_on_container_copy_construction()); }
static
_Alloc
_Select_on_container_copy_construction1
(
const
_Alloc
&
_Al
,
false_type
) {
// get allocator to use, default version
return
(
_Al
); } {
// get allocator to use
return
(
_Select_on_container_copy_construction1
(
_Al
,
_Has_select_on_container_copy_construction
<
_Alloc
>{})); } }; #pragma warning(pop)
template
<
class
_Alloc
>
struct
_Default_allocator_traits
{
// traits for std::allocator
using
allocator_type
=
_Alloc
;
using
value_type
=
typename
_Alloc
::value_type;
using
pointer
=
value_type
*;
using
const_pointer
=
const
value_type
*;
using
void_pointer
=
void
*;
using
const_void_pointer
=
const
void
*;
using
size_type
=
size_t
;
using
difference_type
=
ptrdiff_t
;
using
propagate_on_container_copy_assignment
=
false_type
;
using
propagate_on_container_move_assignment
=
true_type
;
using
propagate_on_container_swap
=
false_type
;
using
is_always_equal
=
true_type
;
template
<
class
_Other
>
using
rebind_alloc
=
allocator
<
_Other
>;
template
<
class
_Other
>
using
rebind_traits
=
allocator_traits
<
allocator
<
_Other
>>; {
// allocate array of _Count elements
return
(
static_cast
<
pointer
>(
_Allocate
<
_New_alignof
<
value_type
>>(
_Get_size_of_n
<
sizeof
(
value_type
)>(
_Count
)))); }
const_void_pointer
) {
// allocate array of _Count elements, with hint
return
(
static_cast
<
pointer
>(
_Allocate
<
_New_alignof
<
value_type
>>(
_Get_size_of_n
<
sizeof
(
value_type
)>(
_Count
)))); }
static
void
deallocate
(
_Alloc
&,
const
pointer
_Ptr
,
const
size_type
_Count
) {
// deallocate _Count elements at _Ptr
// no overflow check on the following multiply; we assume _Allocate did that check
_Deallocate
<
_New_alignof
<
value_type
>>(
_Ptr
,
sizeof
(
value_type
) *
_Count
); }
template
<
class
_Objty
,
class
...
_Types
>
static
void
construct
(
_Alloc
&,
_Objty
*
const
_Ptr
,
_Types
&&...
_Args
) {
// construct _Objty(_Types...) at _Ptr
::
new
(
const_cast
<
void
*>(
static_cast
<
const
volatile
void
*>(
_Ptr
))) }
template
<
class
_Uty
>
static
void
destroy
(
_Alloc
&,
_Uty
*
const
_Ptr
) {
// destroy object at _Ptr
_Ptr
->~_Uty(); } {
// get maximum size
return
(
static_cast
<
size_t
>(-
1
) /
sizeof
(
value_type
)); } {
// get allocator to use
return
(
_Al
); } };
template
<
class
_Alloc
>
struct
allocator_traits
:
conditional_t
<
_Is_default_allocator
<
_Alloc
>::
value
,
_Default_allocator_traits
<
_Alloc
>,
_Normal_allocator_traits
<
_Alloc
>> {
// defines traits for allocators
};
// TYPE TRAIT _Always_equal_after_move
template
<
class
_Alloc
> ||
allocator_traits
<
_Alloc
>::
propagate_on_container_move_assignment
::
value
;
// ALIAS TEMPLATE _Rebind_alloc_t
template
<
class
_Alloc
,
class
_Value_type
>
using
_Rebind_alloc_t
=
typename
allocator_traits
<
_Alloc
>::
template
rebind_alloc
<
_Value_type
>;
// VARIABLE TEMPLATE _Is_simple_alloc_v
template
<
class
_Alloc
>
// tests if allocator has simple addressing
is_same_v
<
typename
allocator_traits
<
_Alloc
>::
size_type
,
size_t
> &&
is_same_v
<
typename
allocator_traits
<
_Alloc
>::
difference_type
,
ptrdiff_t
> &&
is_same_v
<
typename
allocator_traits
<
_Alloc
>::
pointer
,
typename
_Alloc
::value_type *> &&
is_same_v
<
typename
allocator_traits
<
_Alloc
>::
const_pointer
,
const
typename
_Alloc
::value_type *>;
// STRUCT TEMPLATE _Simple_types
template
<
class
_Value_type
>
struct
_Simple_types
{
// wraps types from allocators with simple addressing for use in iterators
// and other SCARY machinery
using
value_type
=
_Value_type
;
using
size_type
=
size_t
;
using
difference_type
=
ptrdiff_t
;
using
pointer
=
value_type
*;
using
const_pointer
=
const
value_type
*; };
// CLASS TEMPLATE allocator
template
<
class
_Ty
>
class
allocator
{
// generic allocator for objects of class _Ty
public
:
static_assert
(!
is_const_v
<
_Ty
>,
"The C++ Standard forbids containers of const elements "
"because allocator<const T> is ill-formed."
);
using
_Not_user_specialized
=
void
;
using
value_type
=
_Ty
;
using
propagate_on_container_move_assignment
=
true_type
;
using
is_always_equal
=
true_type
;
template
<
class
_Other
> {
// convert this type to allocator<_Other>
using
other
=
allocator
<
_Other
>; }; {
// return address of mutable _Val
} {
// return address of nonmutable _Val
}
constexpr
allocator
()
noexcept
{
// construct default allocator (do nothing)
}
constexpr
allocator
(
const
allocator
&)
noexcept
=
default
;
template
<
class
_Other
>
constexpr
allocator
(
const
allocator
<
_Other
>&)
noexcept
{
// construct from a related allocator (do nothing)
}
void
deallocate
(
_Ty
*
const
_Ptr
,
const
size_t
_Count
) {
// deallocate object at _Ptr
// no overflow check on the following multiply; we assume _Allocate did that check
_Deallocate
<
_New_alignof
<
_Ty
>>(
_Ptr
,
sizeof
(
_Ty
) *
_Count
); } {
// allocate array of _Count elements
return
(
static_cast
<
_Ty
*>(
_Allocate
<
_New_alignof
<
_Ty
>>(
_Get_size_of_n
<
sizeof
(
_Ty
)>(
_Count
)))); } {
// allocate array of _Count elements, ignore hint
return
(
allocate
(
_Count
)); }
template
<
class
_Objty
,
class
...
_Types
> {
// construct _Objty(_Types...) at _Ptr
::
new
(
const_cast
<
void
*>(
static_cast
<
const
volatile
void
*>(
_Ptr
))) }
template
<
class
_Uty
> {
// destroy object at _Ptr
_Ptr
->~_Uty(); } {
// estimate maximum array size
return
(
static_cast
<
size_t
>(-
1
) /
sizeof
(
_Ty
)); } };
// CLASS allocator<void>
template
<> {
// generic allocator for type void
public
:
using
value_type
=
void
;
using
pointer
=
void
*;
using
const_pointer
=
const
void
*;
template
<
class
_Other
>
struct
rebind
{
// convert this type to an allocator<_Other>
using
other
=
allocator
<
_Other
>; }; };
template
<
class
_Ty
,
class
_Other
>
const
allocator
<
_Other
>&)
noexcept
{
// test for allocator equality
return
(
true
); }
template
<
class
_Ty
,
class
_Other
>
const
allocator
<
_Other
>&)
noexcept
{
// test for allocator inequality
return
(
false
); }
#if _HAS_CXX17
// ALIAS TEMPLATE _Guide_size_type_t FOR DEDUCTION GUIDES, N4687 26.5.4.1 [unord.map.overview]/4
template<class _Alloc>
using _Guide_size_type_t = typename allocator_traits<
conditional_t<_Is_allocator<_Alloc>::value, _Alloc, allocator<int>>
>::size_type; #endif /* _HAS_CXX17 */
// FUNCTION TEMPLATE _Pocca
template
<
class
_Alloc
>
inline
void
_Pocca
(
_Alloc
&
_Left
,
const
_Alloc
&
_Right
,
true_type
)
noexcept
{
// propagate on container copy assignment
_Left
=
_Right
; }
template
<
class
_Alloc
>
inline
void
_Pocca
(
_Alloc
&,
const
_Alloc
&,
false_type
)
noexcept
{
// (don't) propagate on container copy assignment
}
template
<
class
_Alloc
>
inline
void
_Pocca
(
_Alloc
&
_Left
,
const
_Alloc
&
_Right
)
noexcept
{
// (maybe) propagate on container copy assignment
typename
allocator_traits
<
_Alloc
>::
propagate_on_container_copy_assignment
_Tag
;
_Pocca
(
_Left
,
_Right
,
_Tag
); }
// FUNCTION TEMPLATE _Pocma
template
<
class
_Alloc
>
inline
void
_Pocma
(
_Alloc
&
_Left
,
_Alloc
&
_Right
,
true_type
)
noexcept
{
// propagate on container move assignment
}
template
<
class
_Alloc
>
inline
void
_Pocma
(
_Alloc
&,
_Alloc
&,
false_type
)
noexcept
{
// (don't) propagate on container move assignment
}
template
<
class
_Alloc
>
inline
void
_Pocma
(
_Alloc
&
_Left
,
_Alloc
&
_Right
)
noexcept
{
// (maybe) propagate on container move assignment
typename
allocator_traits
<
_Alloc
>::
propagate_on_container_move_assignment
_Tag
;
_Pocma
(
_Left
,
_Right
,
_Tag
); }
// FUNCTION TEMPLATE _Pocs
template
<
class
_Alloc
>
inline
void
_Pocs
(
_Alloc
&
_Left
,
_Alloc
&
_Right
,
true_type
)
noexcept
{
// propagate on container swap
_Swap_adl
(
_Left
,
_Right
); }
template
<
class
_Alloc
>
inline
void
_Pocs
(
_Alloc
&
_Left
,
_Alloc
&
_Right
,
false_type
)
noexcept
{
// (don't) propagate on container swap
(
void
)
_Left
; (
void
)
_Right
; }
template
<
class
_Alloc
>
inline
void
_Pocs
(
_Alloc
&
_Left
,
_Alloc
&
_Right
)
noexcept
{
// (maybe) propagate on container swap
typename
allocator_traits
<
_Alloc
>::
propagate_on_container_swap
_Tag
;
_Pocs
(
_Left
,
_Right
,
_Tag
); }
// FUNCTION TEMPLATE _Destroy_range WITH ALLOC
template
<
class
_Alloc
>
inline
void
_Destroy_range1
(
typename
allocator_traits
<
_Alloc
>::
pointer
_First
,
typename
allocator_traits
<
_Alloc
>::
pointer
_Last
,
_Alloc
&
_Al
,
false_type
) {
// destroy [_First, _Last), no special optimization
for
(;
_First
!=
_Last
; ++
_First
) {
allocator_traits
<
_Alloc
>::
destroy
(
_Al
,
_Unfancy
(
_First
)); } }
template
<
class
_Alloc
>
inline
void
_Destroy_range1
(
typename
allocator_traits
<
_Alloc
>::
pointer
,
typename
allocator_traits
<
_Alloc
>::
pointer
,
_Alloc
&,
true_type
) {
// destroy [_First, _Last), trivially destructible and default destroy
// nothing to do
}
template
<
class
_Alloc
>
inline
void
_Destroy_range
(
typename
allocator_traits
<
_Alloc
>::
pointer
_First
,
typename
allocator_traits
<
_Alloc
>::
pointer
_Last
,
_Alloc
&
_Al
) {
// destroy [_First, _Last), choose optimization
// note that this is an optimization for debug mode codegen;
// in release mode the BE removes all of this
using
_Val
=
typename
_Alloc
::value_type;
_Destroy_range1
(
_First
,
_Last
,
_Al
,
bool_constant
<
conjunction_v
<
is_trivially_destructible
<
_Val
>,
_Uses_default_destroy
<
_Alloc
,
_Val
*>>>{}); }
// FUNCTION TEMPLATE _Destroy_range
template
<
class
_FwdIt
>
inline
void
_Destroy_range1
(
_FwdIt
_First
,
_FwdIt
_Last
,
false_type
) {
// destroy [_First, _Last), no special optimization
for
(;
_First
!=
_Last
; ++
_First
) {
_Destroy_in_place
(*
_First
); } }
template
<
class
_FwdIt
>
inline
void
_Destroy_range1
(
_FwdIt
,
_FwdIt
,
true_type
) {
// destroy [_First, _Last), trivially destructible
// nothing to do
}
template
<
class
_FwdIt
>
inline
void
_Destroy_range
(
_FwdIt
_First
,
_FwdIt
_Last
) {
// destroy [_First, _Last), choose optimization
// note that this is an optimization for debug mode codegen;
// in release mode the BE removes all of this
_Destroy_range1
(
_First
,
_Last
,
is_trivially_destructible
<
_Iter_value_t
<
_FwdIt
>>()); }
// FUNCTION TEMPLATE _Convert_size
template
<
class
_Size_type
>
inline
_Size_type
_Convert_size
(
const
size_t
_Len
) {
// convert size_t to _Size_type, avoiding truncation
if
(
_Len
> (
numeric_limits
<
_Size_type
>::
max
)()) {
_Xlength_error
(
"size_t too long for _Size_type"
); }
return
(
static_cast
<
_Size_type
>(
_Len
)); }
template
<>
inline
size_t
_Convert_size
<
size_t
>(
const
size_t
_Len
) {
// convert size_t to size_t, unchanged
return
(
_Len
); }
// FUNCTION TEMPLATE _Deallocate_plain
template
<
class
_Alloc
,
enable_if_t
<
is_same_v
<
typename
allocator_traits
<
_Alloc
>::
pointer
,
typename
_Alloc
::value_type *>,
int
> =
0
>
inline
void
_Deallocate_plain
(
_Alloc
&
_Al
,
typename
_Alloc
::value_type *
const
_Ptr
) {
// deallocate a plain pointer using an allocator, non-fancy pointers special case
allocator_traits
<
_Alloc
>::
deallocate
(
_Al
,
_Ptr
,
1
); }
template
<
class
_Alloc
,
enable_if_t
<!
is_same_v
<
typename
allocator_traits
<
_Alloc
>::
pointer
,
typename
_Alloc
::value_type *>,
int
> =
0
>
inline
void
_Deallocate_plain
(
_Alloc
&
_Al
,
typename
_Alloc
::value_type *
const
_Ptr
) {
// deallocate a plain pointer using an allocator
using
_Alloc_traits
=
allocator_traits
<
_Alloc
>;
using
_Ptr_traits
=
pointer_traits
<
typename
_Alloc_traits
::
pointer
>;
_Alloc_traits
::
deallocate
(
_Al
,
_Ptr_traits
::
pointer_to
(*
_Ptr
),
1
); }
// ATOMIC REFERENCE COUNTING PRIMITIVES
#include <xatomic0.h>
#if _USE_INTERLOCKED_REFCOUNTING #include <intrin0.h>
#define _MT_INCR(x) \
_InterlockedIncrement(reinterpret_cast<volatile long *>(&x))
#define _MT_DECR(x) \
_InterlockedDecrement(reinterpret_cast<volatile long *>(&x))
#else /* _USE_INTERLOCKED_REFCOUNTING */
#include <xatomic.h>
#define _MT_INCR(x) \
_Inc_atomic_counter_explicit(x, memory_order_relaxed)
#define _MT_DECR(x) \
_Dec_atomic_counter_explicit(x, memory_order_acq_rel) #endif /* _USE_INTERLOCKED_REFCOUNTING */
#pragma pop_macro("new")
_STL_RESTORE_CLANG_WARNINGS
/* * Copyright (c) by P.J. Plauger. All rights reserved. * Consult your license regarding permissions and restrictions. V6.50:0009 */