1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___RANGES_CONCEPTS_H 11 #define _LIBCPP___RANGES_CONCEPTS_H 12 13 #include <__concepts/constructible.h> 14 #include <__concepts/movable.h> 15 #include <__concepts/same_as.h> 16 #include <__config> 17 #include <__iterator/concepts.h> 18 #include <__iterator/incrementable_traits.h> 19 #include <__iterator/iter_move.h> 20 #include <__iterator/iterator_traits.h> 21 #include <__iterator/readable_traits.h> 22 #include <__ranges/access.h> 23 #include <__ranges/data.h> 24 #include <__ranges/enable_borrowed_range.h> 25 #include <__ranges/enable_view.h> 26 #include <__ranges/size.h> 27 #include <__type_traits/add_pointer.h> 28 #include <__type_traits/is_reference.h> 29 #include <__type_traits/remove_cvref.h> 30 #include <__type_traits/remove_reference.h> 31 #include <__utility/declval.h> 32 #include <initializer_list> 33 34 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 35 # pragma GCC system_header 36 #endif 37 38 _LIBCPP_BEGIN_NAMESPACE_STD 39 40 #if _LIBCPP_STD_VER >= 20 41 42 namespace ranges { 43 44 // [range.range] 45 46 template <class _Tp> requires(_Tp & __t)47 concept range = requires(_Tp& __t) { 48 ranges::begin(__t); // sometimes equality-preserving 49 ranges::end(__t); 50 }; 51 52 template <class _Tp> 53 concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>; 54 55 template<class _Range> 56 concept borrowed_range = range<_Range> && 57 (is_lvalue_reference_v<_Range> || enable_borrowed_range<remove_cvref_t<_Range>>); 58 59 // `iterator_t` defined in <__ranges/access.h> 60 61 template <range _Rp> 62 using sentinel_t = decltype(ranges::end(std::declval<_Rp&>())); 63 64 template <range _Rp> 65 using range_difference_t = iter_difference_t<iterator_t<_Rp>>; 66 67 template <range _Rp> 68 using range_value_t = iter_value_t<iterator_t<_Rp>>; 69 70 template <range _Rp> 71 using range_reference_t = iter_reference_t<iterator_t<_Rp>>; 72 73 template <range _Rp> 74 using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>; 75 76 template <range _Rp> 77 using range_common_reference_t = iter_common_reference_t<iterator_t<_Rp>>; 78 79 // [range.sized] 80 template <class _Tp> requires(_Tp & __t)81 concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); }; 82 83 template<sized_range _Rp> 84 using range_size_t = decltype(ranges::size(std::declval<_Rp&>())); 85 86 // `disable_sized_range` defined in `<__ranges/size.h>` 87 88 // [range.view], views 89 90 // `enable_view` defined in <__ranges/enable_view.h> 91 // `view_base` defined in <__ranges/enable_view.h> 92 93 template <class _Tp> 94 concept view = 95 range<_Tp> && 96 movable<_Tp> && 97 enable_view<_Tp>; 98 99 template <class _Range> 100 concept __simple_view = 101 view<_Range> && range<const _Range> && 102 same_as<iterator_t<_Range>, iterator_t<const _Range>> && 103 same_as<sentinel_t<_Range>, sentinel_t<const _Range>>; 104 105 // [range.refinements], other range refinements 106 template <class _Rp, class _Tp> 107 concept output_range = range<_Rp> && output_iterator<iterator_t<_Rp>, _Tp>; 108 109 template <class _Tp> 110 concept forward_range = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>; 111 112 template <class _Tp> 113 concept bidirectional_range = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>; 114 115 template <class _Tp> 116 concept random_access_range = 117 bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>; 118 119 template<class _Tp> 120 concept contiguous_range = 121 random_access_range<_Tp> && 122 contiguous_iterator<iterator_t<_Tp>> && requires(_Tp & __t)123 requires(_Tp& __t) { 124 { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>; 125 }; 126 127 template <class _Tp> 128 concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>; 129 130 template <class _Tp> 131 inline constexpr bool __is_std_initializer_list = false; 132 133 template <class _Ep> 134 inline constexpr bool __is_std_initializer_list<initializer_list<_Ep>> = true; 135 136 template <class _Tp> 137 concept viewable_range = 138 range<_Tp> && 139 ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) || 140 (!view<remove_cvref_t<_Tp>> && 141 (is_lvalue_reference_v<_Tp> || 142 (movable<remove_reference_t<_Tp>> && !__is_std_initializer_list<remove_cvref_t<_Tp>>)))); 143 144 } // namespace ranges 145 146 #endif // _LIBCPP_STD_VER >= 20 147 148 _LIBCPP_END_NAMESPACE_STD 149 150 #endif // _LIBCPP___RANGES_CONCEPTS_H 151