зеркало из https://github.com/microsoft/STL.git
527 строки
18 KiB
C++
527 строки
18 KiB
C++
// __msvc_iter_core.hpp internal header (core)
|
|
|
|
// Copyright (c) Microsoft Corporation.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef __MSVC_ITER_CORE_HPP
|
|
#define __MSVC_ITER_CORE_HPP
|
|
#include <yvals_core.h>
|
|
#if _STL_COMPILER_PREPROCESSOR
|
|
#include <utility>
|
|
|
|
#pragma pack(push, _CRT_PACKING)
|
|
#pragma warning(push, _STL_WARNING_LEVEL)
|
|
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
|
_STL_DISABLE_CLANG_WARNINGS
|
|
#pragma push_macro("new")
|
|
#undef new
|
|
|
|
_STD_BEGIN
|
|
template <class _Ty, class _Alloc, class = void>
|
|
struct _Has_allocator_type : false_type {}; // tests for suitable _Ty::allocator_type
|
|
|
|
template <class _Ty, class _Alloc>
|
|
struct _Has_allocator_type<_Ty, _Alloc, void_t<typename _Ty::allocator_type>>
|
|
: is_convertible<_Alloc, typename _Ty::allocator_type>::type {};
|
|
|
|
_EXPORT_STD struct allocator_arg_t { // tag type for added allocator argument
|
|
explicit allocator_arg_t() = default;
|
|
};
|
|
|
|
_EXPORT_STD _INLINE_VAR constexpr allocator_arg_t allocator_arg{};
|
|
|
|
_EXPORT_STD template <class _Ty, class _Alloc>
|
|
struct uses_allocator : _Has_allocator_type<_Ty, _Alloc>::type {};
|
|
|
|
_EXPORT_STD template <class _Ty, class _Alloc>
|
|
_INLINE_VAR constexpr bool uses_allocator_v = uses_allocator<_Ty, _Alloc>::value;
|
|
|
|
// from <iterator>
|
|
_EXPORT_STD struct input_iterator_tag {};
|
|
|
|
_EXPORT_STD struct output_iterator_tag {};
|
|
|
|
_EXPORT_STD struct forward_iterator_tag : input_iterator_tag {};
|
|
|
|
_EXPORT_STD struct bidirectional_iterator_tag : forward_iterator_tag {};
|
|
|
|
_EXPORT_STD struct random_access_iterator_tag : bidirectional_iterator_tag {};
|
|
|
|
#ifdef __cpp_lib_concepts
|
|
_EXPORT_STD struct contiguous_iterator_tag : random_access_iterator_tag {};
|
|
|
|
template <class _Ty>
|
|
using _With_reference = _Ty&;
|
|
|
|
template <class _Ty>
|
|
concept _Can_reference = requires { typename _With_reference<_Ty>; };
|
|
|
|
template <class _Ty>
|
|
concept _Dereferenceable = requires(_Ty& __t) {
|
|
{ *__t } -> _Can_reference;
|
|
};
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_iterator_concept = requires { typename _Ty::iterator_concept; };
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_iterator_category = requires { typename _Ty::iterator_category; };
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_value_type = requires { typename _Ty::value_type; };
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_element_type = requires { typename _Ty::element_type; };
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_difference_type = requires { typename _Ty::difference_type; };
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_pointer = requires { typename _Ty::pointer; };
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_reference = requires { typename _Ty::reference; };
|
|
|
|
_EXPORT_STD template <class>
|
|
struct incrementable_traits {};
|
|
|
|
template <class _Ty>
|
|
requires is_object_v<_Ty>
|
|
struct incrementable_traits<_Ty*> {
|
|
using difference_type = ptrdiff_t;
|
|
};
|
|
|
|
template <class _Ty>
|
|
struct incrementable_traits<const _Ty> : incrementable_traits<_Ty> {};
|
|
|
|
template <_Has_member_difference_type _Ty>
|
|
struct incrementable_traits<_Ty> {
|
|
using difference_type = _Ty::difference_type;
|
|
};
|
|
|
|
template <class _Ty>
|
|
concept _Can_difference = requires(const _Ty& __a, const _Ty& __b) {
|
|
{ __a - __b } -> integral;
|
|
};
|
|
|
|
template <class _Ty>
|
|
requires (!_Has_member_difference_type<_Ty> && _Can_difference<_Ty>)
|
|
struct incrementable_traits<_Ty> {
|
|
using difference_type = make_signed_t<decltype(_STD declval<_Ty>() - _STD declval<_Ty>())>;
|
|
};
|
|
|
|
template <class _Ty>
|
|
concept _Is_from_primary = _Same_impl<typename _Ty::_From_primary, _Ty>;
|
|
|
|
_EXPORT_STD template <class>
|
|
struct iterator_traits;
|
|
|
|
_EXPORT_STD template <class _Ty>
|
|
using iter_difference_t = conditional_t<_Is_from_primary<iterator_traits<remove_cvref_t<_Ty>>>,
|
|
incrementable_traits<remove_cvref_t<_Ty>>, iterator_traits<remove_cvref_t<_Ty>>>::difference_type;
|
|
|
|
template <class>
|
|
struct _Cond_value_type {};
|
|
|
|
template <class _Ty>
|
|
requires is_object_v<_Ty>
|
|
struct _Cond_value_type<_Ty> {
|
|
using value_type = remove_cv_t<_Ty>;
|
|
};
|
|
|
|
_EXPORT_STD template <class>
|
|
struct indirectly_readable_traits {};
|
|
|
|
template <class _Ty>
|
|
struct indirectly_readable_traits<_Ty*> : _Cond_value_type<_Ty> {};
|
|
|
|
template <class _Ty>
|
|
requires is_array_v<_Ty>
|
|
struct indirectly_readable_traits<_Ty> {
|
|
using value_type = remove_cv_t<remove_extent_t<_Ty>>;
|
|
};
|
|
|
|
template <class _Ty>
|
|
struct indirectly_readable_traits<const _Ty> : indirectly_readable_traits<_Ty> {};
|
|
|
|
template <_Has_member_value_type _Ty>
|
|
struct indirectly_readable_traits<_Ty> : _Cond_value_type<typename _Ty::value_type> {};
|
|
|
|
template <_Has_member_element_type _Ty>
|
|
struct indirectly_readable_traits<_Ty> : _Cond_value_type<typename _Ty::element_type> {};
|
|
|
|
template <_Has_member_value_type _Ty>
|
|
requires _Has_member_element_type<_Ty>
|
|
struct indirectly_readable_traits<_Ty> {};
|
|
|
|
template <_Has_member_value_type _Ty>
|
|
requires _Has_member_element_type<_Ty>
|
|
&& same_as<remove_cv_t<typename _Ty::value_type>, remove_cv_t<typename _Ty::element_type>>
|
|
struct indirectly_readable_traits<_Ty> : _Cond_value_type<typename _Ty::value_type> {};
|
|
|
|
_EXPORT_STD template <class _Ty>
|
|
using iter_value_t = conditional_t<_Is_from_primary<iterator_traits<remove_cvref_t<_Ty>>>,
|
|
indirectly_readable_traits<remove_cvref_t<_Ty>>, iterator_traits<remove_cvref_t<_Ty>>>::value_type;
|
|
|
|
_EXPORT_STD template <_Dereferenceable _Ty>
|
|
using iter_reference_t = decltype(*_STD declval<_Ty&>());
|
|
|
|
template <class>
|
|
struct _Iterator_traits_base {};
|
|
|
|
template <class _It>
|
|
concept _Has_iter_types = _Has_member_difference_type<_It> && _Has_member_value_type<_It> && _Has_member_reference<_It>
|
|
&& _Has_member_iterator_category<_It>;
|
|
|
|
template <bool _Has_member_typedef>
|
|
struct _Old_iter_traits_pointer {
|
|
template <class _It>
|
|
using _Apply = _It::pointer;
|
|
};
|
|
|
|
template <>
|
|
struct _Old_iter_traits_pointer<false> {
|
|
template <class>
|
|
using _Apply = void;
|
|
};
|
|
|
|
template <_Has_iter_types _It>
|
|
struct _Iterator_traits_base<_It> {
|
|
using iterator_category = _It::iterator_category;
|
|
using value_type = _It::value_type;
|
|
using difference_type = _It::difference_type;
|
|
using pointer = _Old_iter_traits_pointer<_Has_member_pointer<_It>>::template _Apply<_It>;
|
|
using reference = _It::reference;
|
|
};
|
|
|
|
template <bool _Has_member_typedef>
|
|
struct _Iter_traits_difference {
|
|
template <class _It>
|
|
using _Apply = incrementable_traits<_It>::difference_type;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_difference<false> {
|
|
template <class>
|
|
using _Apply = void;
|
|
};
|
|
|
|
// clang-format off
|
|
template <class _It>
|
|
concept _Cpp17_iterator =
|
|
requires(_It __i) {
|
|
{ *__i } -> _Can_reference;
|
|
{ ++__i } -> same_as<_It&>;
|
|
{ *__i++ } -> _Can_reference;
|
|
}
|
|
&& copyable<_It>;
|
|
|
|
template <class _It>
|
|
concept _Cpp17_input_iterator = _Cpp17_iterator<_It>
|
|
&& equality_comparable<_It>
|
|
&& _Has_member_difference_type<incrementable_traits<_It>>
|
|
&& _Has_member_value_type<indirectly_readable_traits<_It>>
|
|
&& requires(_It __i) {
|
|
typename common_reference_t<iter_reference_t<_It>&&, typename indirectly_readable_traits<_It>::value_type&>;
|
|
typename common_reference_t<decltype(*__i++)&&, typename indirectly_readable_traits<_It>::value_type&>;
|
|
requires signed_integral<typename incrementable_traits<_It>::difference_type>;
|
|
};
|
|
|
|
template <class _It>
|
|
requires (!_Has_iter_types<_It> && _Cpp17_iterator<_It> && !_Cpp17_input_iterator<_It>)
|
|
struct _Iterator_traits_base<_It> {
|
|
using iterator_category = output_iterator_tag;
|
|
using value_type = void;
|
|
using difference_type =
|
|
_Iter_traits_difference<_Has_member_difference_type<incrementable_traits<_It>>>::template _Apply<_It>;
|
|
using pointer = void;
|
|
using reference = void;
|
|
};
|
|
// clang-format on
|
|
|
|
enum class _Itraits_pointer_strategy { _Use_void, _Use_member, _Use_decltype };
|
|
|
|
template <_Itraits_pointer_strategy>
|
|
struct _Iter_traits_pointer;
|
|
|
|
template <>
|
|
struct _Iter_traits_pointer<_Itraits_pointer_strategy::_Use_void> {
|
|
template <class>
|
|
using _Apply = void;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_pointer<_Itraits_pointer_strategy::_Use_member> {
|
|
template <class _It>
|
|
using _Apply = _It::pointer;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_pointer<_Itraits_pointer_strategy::_Use_decltype> {
|
|
template <class _It>
|
|
using _Apply = decltype(_STD declval<_It&>().operator->());
|
|
};
|
|
|
|
template <class _Ty>
|
|
concept _Has_member_arrow = requires(_Ty&& __t) { static_cast<_Ty&&>(__t).operator->(); };
|
|
|
|
template <bool _Has_member_typedef>
|
|
struct _Iter_traits_reference {
|
|
template <class _It>
|
|
using _Apply = _It::reference;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_reference<false> {
|
|
template <class _It>
|
|
using _Apply = iter_reference_t<_It>;
|
|
};
|
|
|
|
template <bool _Is_random>
|
|
struct _Iter_traits_category4 {
|
|
using type = random_access_iterator_tag;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_category4<false> {
|
|
using type = bidirectional_iterator_tag;
|
|
};
|
|
|
|
// clang-format off
|
|
template <class _It>
|
|
concept _Cpp17_random_delta = totally_ordered<_It>
|
|
&& requires(_It __i, incrementable_traits<_It>::difference_type __n) {
|
|
{ __i += __n } -> same_as<_It&>;
|
|
{ __i -= __n } -> same_as<_It&>;
|
|
{ __i + __n } -> same_as<_It>;
|
|
{ __n + __i } -> same_as<_It>;
|
|
{ __i - __n } -> same_as<_It>;
|
|
{ __i - __i } -> same_as<decltype(__n)>;
|
|
{ __i[__n] } -> convertible_to<iter_reference_t<_It>>;
|
|
};
|
|
// clang-format on
|
|
|
|
template <bool _Is_bidi>
|
|
struct _Iter_traits_category3 {
|
|
template <class _It>
|
|
using _Apply = _Iter_traits_category4<_Cpp17_random_delta<_It>>::type;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_category3<false> {
|
|
template <class>
|
|
using _Apply = forward_iterator_tag;
|
|
};
|
|
|
|
template <class _It>
|
|
concept _Cpp17_bidi_delta = requires(_It __i) {
|
|
{ --__i } -> same_as<_It&>;
|
|
{ __i-- } -> convertible_to<const _It&>;
|
|
requires same_as<decltype(*__i--), iter_reference_t<_It>>;
|
|
};
|
|
|
|
template <bool _Is_forward>
|
|
struct _Iter_traits_category2 {
|
|
template <class _It>
|
|
using _Apply = _Iter_traits_category3<_Cpp17_bidi_delta<_It>>::template _Apply<_It>;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_category2<false> {
|
|
template <class>
|
|
using _Apply = input_iterator_tag;
|
|
};
|
|
|
|
// clang-format off
|
|
template <class _It>
|
|
concept _Cpp17_forward_delta = constructible_from<_It> && is_reference_v<iter_reference_t<_It>>
|
|
&& same_as<remove_cvref_t<iter_reference_t<_It>>, typename indirectly_readable_traits<_It>::value_type>
|
|
&& requires(_It __i) {
|
|
{ __i++ } -> convertible_to<const _It&>;
|
|
requires same_as<decltype(*__i++), iter_reference_t<_It>>;
|
|
};
|
|
// clang-format on
|
|
|
|
template <bool _Has_member_typedef>
|
|
struct _Iter_traits_category {
|
|
template <class _It>
|
|
using _Apply = _It::iterator_category;
|
|
};
|
|
|
|
template <>
|
|
struct _Iter_traits_category<false> {
|
|
template <class _It>
|
|
using _Apply = _Iter_traits_category2<_Cpp17_forward_delta<_It>>::template _Apply<_It>;
|
|
};
|
|
|
|
// clang-format off
|
|
template <class _It>
|
|
requires (!_Has_iter_types<_It> && _Cpp17_input_iterator<_It>)
|
|
struct _Iterator_traits_base<_It> {
|
|
using iterator_category = _Iter_traits_category<_Has_member_iterator_category<_It>>::template _Apply<_It>;
|
|
using value_type = indirectly_readable_traits<_It>::value_type;
|
|
using difference_type = incrementable_traits<_It>::difference_type;
|
|
using pointer = _Iter_traits_pointer<(
|
|
_Has_member_pointer<_It> ? _Itraits_pointer_strategy::_Use_member
|
|
: _Has_member_arrow<_It&> ? _Itraits_pointer_strategy::_Use_decltype
|
|
: _Itraits_pointer_strategy::_Use_void)>::template _Apply<_It>;
|
|
using reference = _Iter_traits_reference<_Has_member_reference<_It>>::template _Apply<_It>;
|
|
};
|
|
// clang-format on
|
|
|
|
_EXPORT_STD template <class _Ty>
|
|
struct iterator_traits : _Iterator_traits_base<_Ty> {
|
|
using _From_primary = iterator_traits;
|
|
};
|
|
|
|
template <class _Ty>
|
|
requires is_object_v<_Ty>
|
|
struct iterator_traits<_Ty*> {
|
|
using iterator_concept = contiguous_iterator_tag;
|
|
using iterator_category = random_access_iterator_tag;
|
|
using value_type = remove_cv_t<_Ty>;
|
|
using difference_type = ptrdiff_t;
|
|
using pointer = _Ty*;
|
|
using reference = _Ty&;
|
|
};
|
|
|
|
template <class _Ty>
|
|
inline constexpr bool _Integer_class = requires {
|
|
typename _Ty::_Signed_type;
|
|
typename _Ty::_Unsigned_type;
|
|
};
|
|
|
|
template <class _Ty>
|
|
concept _Integer_like = _Is_nonbool_integral<remove_cv_t<_Ty>> || _Integer_class<_Ty>;
|
|
|
|
template <class _Ty>
|
|
concept _Signed_integer_like = _Integer_like<_Ty> && static_cast<_Ty>(-1) < static_cast<_Ty>(0);
|
|
|
|
// clang-format off
|
|
_EXPORT_STD template <class _Ty>
|
|
concept weakly_incrementable = movable<_Ty>
|
|
&& requires(_Ty __i) {
|
|
typename iter_difference_t<_Ty>;
|
|
requires _Signed_integer_like<iter_difference_t<_Ty>>;
|
|
{ ++__i } -> same_as<_Ty&>;
|
|
__i++;
|
|
}
|
|
#ifdef __clang__ // TRANSITION, LLVM-48173
|
|
&& !same_as<_Ty, bool>
|
|
#endif // TRANSITION, LLVM-48173
|
|
;
|
|
|
|
_EXPORT_STD template <class _It>
|
|
concept input_or_output_iterator = requires(_It __i) { { *__i } -> _Can_reference; }
|
|
&& weakly_incrementable<_It>;
|
|
|
|
_EXPORT_STD template <class _Se, class _It>
|
|
concept sentinel_for = semiregular<_Se>
|
|
&& input_or_output_iterator<_It>
|
|
&& _Weakly_equality_comparable_with<_Se, _It>;
|
|
// clang-format on
|
|
|
|
_EXPORT_STD template <class _Se, class _It>
|
|
inline constexpr bool disable_sized_sentinel_for = false;
|
|
|
|
// clang-format off
|
|
_EXPORT_STD template <class _Se, class _It>
|
|
concept sized_sentinel_for = sentinel_for<_Se, _It>
|
|
&& !disable_sized_sentinel_for<remove_cv_t<_Se>, remove_cv_t<_It>>
|
|
&& requires(const _It& __i, const _Se& __s) {
|
|
{ __s - __i } -> same_as<iter_difference_t<_It>>;
|
|
{ __i - __s } -> same_as<iter_difference_t<_It>>;
|
|
};
|
|
// clang-format on
|
|
|
|
_EXPORT_STD struct default_sentinel_t {};
|
|
|
|
_EXPORT_STD inline constexpr default_sentinel_t default_sentinel{};
|
|
|
|
namespace ranges {
|
|
_EXPORT_STD enum class subrange_kind : bool { unsized, sized };
|
|
|
|
_EXPORT_STD template <input_or_output_iterator _It, sentinel_for<_It> _Se = _It,
|
|
subrange_kind _Ki = sized_sentinel_for<_Se, _It> ? subrange_kind::sized : subrange_kind::unsized>
|
|
requires (_Ki == subrange_kind::sized || !sized_sentinel_for<_Se, _It>)
|
|
class subrange;
|
|
|
|
_EXPORT_STD template <size_t _Idx, class _It, class _Se, subrange_kind _Ki>
|
|
requires ((_Idx == 0 && copyable<_It>) || _Idx == 1)
|
|
_NODISCARD constexpr auto get(const subrange<_It, _Se, _Ki>& _Val);
|
|
|
|
_EXPORT_STD template <size_t _Idx, class _It, class _Se, subrange_kind _Ki>
|
|
requires (_Idx < 2)
|
|
_NODISCARD constexpr auto get(subrange<_It, _Se, _Ki>&& _Val);
|
|
} // namespace ranges
|
|
|
|
_EXPORT_STD using ranges::get;
|
|
|
|
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
|
inline constexpr bool _Is_subrange_v<ranges::subrange<_It, _Se, _Ki>> = true;
|
|
|
|
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
|
struct tuple_size<ranges::subrange<_It, _Se, _Ki>> : integral_constant<size_t, 2> {};
|
|
|
|
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
|
struct tuple_element<0, ranges::subrange<_It, _Se, _Ki>> {
|
|
using type = _It;
|
|
};
|
|
|
|
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
|
struct tuple_element<1, ranges::subrange<_It, _Se, _Ki>> {
|
|
using type = _Se;
|
|
};
|
|
|
|
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
|
struct tuple_element<0, const ranges::subrange<_It, _Se, _Ki>> {
|
|
using type = _It;
|
|
};
|
|
|
|
template <class _It, class _Se, ranges::subrange_kind _Ki>
|
|
struct tuple_element<1, const ranges::subrange<_It, _Se, _Ki>> {
|
|
using type = _Se;
|
|
};
|
|
#else // ^^^ defined(__cpp_lib_concepts) / !defined(__cpp_lib_concepts) vvv
|
|
template <class, class = void>
|
|
struct _Iterator_traits_base {}; // empty for non-iterators
|
|
|
|
template <class _Iter>
|
|
struct _Iterator_traits_base<_Iter,
|
|
void_t<typename _Iter::iterator_category, typename _Iter::value_type, typename _Iter::difference_type,
|
|
typename _Iter::pointer, typename _Iter::reference>> {
|
|
// defined if _Iter::* types exist
|
|
using iterator_category = typename _Iter::iterator_category;
|
|
using value_type = typename _Iter::value_type;
|
|
using difference_type = typename _Iter::difference_type;
|
|
using pointer = typename _Iter::pointer;
|
|
using reference = typename _Iter::reference;
|
|
};
|
|
|
|
template <class _Ty, bool = is_object_v<_Ty>>
|
|
struct _Iterator_traits_pointer_base { // iterator properties for pointers to object
|
|
using iterator_category = random_access_iterator_tag;
|
|
using value_type = remove_cv_t<_Ty>;
|
|
using difference_type = ptrdiff_t;
|
|
using pointer = _Ty*;
|
|
using reference = _Ty&;
|
|
};
|
|
|
|
template <class _Ty>
|
|
struct _Iterator_traits_pointer_base<_Ty, false> {}; // iterator non-properties for pointers to non-object
|
|
|
|
template <class _Iter>
|
|
struct iterator_traits : _Iterator_traits_base<_Iter> {}; // get traits from iterator _Iter, if possible
|
|
|
|
template <class _Ty>
|
|
struct iterator_traits<_Ty*> : _Iterator_traits_pointer_base<_Ty> {}; // get traits from pointer, if possible
|
|
#endif // ^^^ !defined(__cpp_lib_concepts) ^^^
|
|
_STD_END
|
|
|
|
#pragma pop_macro("new")
|
|
_STL_RESTORE_CLANG_WARNINGS
|
|
#pragma warning(pop)
|
|
#pragma pack(pop)
|
|
#endif // _STL_COMPILER_PREPROCESSOR
|
|
#endif // __MSVC_ITER_CORE_HPP
|