master
  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/common_reference_with.h>
 14#include <__concepts/constructible.h>
 15#include <__concepts/convertible_to.h>
 16#include <__concepts/movable.h>
 17#include <__concepts/same_as.h>
 18#include <__config>
 19#include <__iterator/concepts.h>
 20#include <__iterator/incrementable_traits.h>
 21#include <__iterator/iter_move.h>
 22#include <__iterator/iterator_traits.h>
 23#include <__iterator/readable_traits.h>
 24#include <__ranges/access.h>
 25#include <__ranges/data.h>
 26#include <__ranges/enable_borrowed_range.h>
 27#include <__ranges/enable_view.h>
 28#include <__ranges/size.h>
 29#include <__type_traits/add_pointer.h>
 30#include <__type_traits/common_reference.h>
 31#include <__type_traits/common_type.h>
 32#include <__type_traits/is_reference.h>
 33#include <__type_traits/remove_cvref.h>
 34#include <__type_traits/remove_reference.h>
 35#include <__utility/declval.h>
 36#include <initializer_list>
 37
 38#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 39#  pragma GCC system_header
 40#endif
 41
 42_LIBCPP_BEGIN_NAMESPACE_STD
 43
 44#if _LIBCPP_STD_VER >= 20
 45
 46namespace ranges {
 47
 48// [range.range]
 49
 50template <class _Tp>
 51concept range = requires(_Tp& __t) {
 52  ranges::begin(__t); // sometimes equality-preserving
 53  ranges::end(__t);
 54};
 55
 56template <class _Tp>
 57concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
 58
 59template <class _Range>
 60concept borrowed_range =
 61    range<_Range> && (is_lvalue_reference_v<_Range> || enable_borrowed_range<remove_cvref_t<_Range>>);
 62
 63// `iterator_t` defined in <__ranges/access.h>
 64
 65template <range _Rp>
 66using sentinel_t = decltype(ranges::end(std::declval<_Rp&>()));
 67
 68template <range _Rp>
 69using range_difference_t = iter_difference_t<iterator_t<_Rp>>;
 70
 71template <range _Rp>
 72using range_value_t = iter_value_t<iterator_t<_Rp>>;
 73
 74template <range _Rp>
 75using range_reference_t = iter_reference_t<iterator_t<_Rp>>;
 76
 77template <range _Rp>
 78using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
 79
 80template <range _Rp>
 81using range_common_reference_t = iter_common_reference_t<iterator_t<_Rp>>;
 82
 83// [range.sized]
 84template <class _Tp>
 85concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
 86
 87template <sized_range _Rp>
 88using range_size_t = decltype(ranges::size(std::declval<_Rp&>()));
 89
 90// `disable_sized_range` defined in `<__ranges/size.h>`
 91
 92// [range.view], views
 93
 94// `enable_view` defined in <__ranges/enable_view.h>
 95// `view_base` defined in <__ranges/enable_view.h>
 96
 97template <class _Tp>
 98concept view = range<_Tp> && movable<_Tp> && enable_view<_Tp>;
 99
100template <class _Range>
101concept __simple_view =
102    view<_Range> && range<const _Range> && 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
106template <class _Rp, class _Tp>
107concept output_range = range<_Rp> && output_iterator<iterator_t<_Rp>, _Tp>;
108
109template <class _Tp>
110concept forward_range = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
111
112template <class _Tp>
113concept bidirectional_range = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
114
115template <class _Tp>
116concept random_access_range = bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
117
118template <class _Tp>
119concept contiguous_range = random_access_range<_Tp> && contiguous_iterator<iterator_t<_Tp>> && requires(_Tp& __t) {
120  { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
121};
122
123template <class _Tp>
124concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
125
126template <class _Tp>
127inline constexpr bool __is_std_initializer_list = false;
128
129template <class _Ep>
130inline constexpr bool __is_std_initializer_list<initializer_list<_Ep>> = true;
131
132template <class _Tp>
133concept viewable_range =
134    range<_Tp> &&
135    ((view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) ||
136     (!view<remove_cvref_t<_Tp>> &&
137      (is_lvalue_reference_v<_Tp> ||
138       (movable<remove_reference_t<_Tp>> && !__is_std_initializer_list<remove_cvref_t<_Tp>>))));
139
140#  if _LIBCPP_STD_VER >= 23
141
142template <class... _Rs>
143using __concat_reference_t _LIBCPP_NODEBUG = common_reference_t<range_reference_t<_Rs>...>;
144
145template <class... _Rs>
146using __concat_value_t _LIBCPP_NODEBUG = common_type_t<range_value_t<_Rs>...>;
147
148template <class... _Rs>
149using __concat_rvalue_reference_t _LIBCPP_NODEBUG = common_reference_t<range_rvalue_reference_t<_Rs>...>;
150
151template <class _Ref, class _RRef, class _It>
152concept __concat_indirectly_readable_impl = requires(const _It __it) {
153  { *__it } -> convertible_to<_Ref>;
154  { ranges::iter_move(__it) } -> convertible_to<_RRef>;
155};
156
157template <class... _Rs>
158concept __concat_indirectly_readable =
159    common_reference_with<__concat_reference_t<_Rs...>&&, __concat_value_t<_Rs...>&> &&
160    common_reference_with<__concat_reference_t<_Rs...>&&, __concat_rvalue_reference_t<_Rs...>&&> &&
161    common_reference_with<__concat_rvalue_reference_t<_Rs...>&&, const __concat_value_t<_Rs...>&> &&
162    (__concat_indirectly_readable_impl<__concat_reference_t<_Rs...>,
163                                       __concat_rvalue_reference_t<_Rs...>,
164                                       iterator_t<_Rs>> &&
165     ...);
166
167template <class... _Rs>
168concept __concatable = requires {
169  typename __concat_reference_t<_Rs...>;
170  typename __concat_value_t<_Rs...>;
171  typename __concat_rvalue_reference_t<_Rs...>;
172} && __concat_indirectly_readable<_Rs...>;
173
174#  endif // _LIBCPP_STD_VER >= 23
175
176} // namespace ranges
177
178#endif // _LIBCPP_STD_VER >= 20
179
180_LIBCPP_END_NAMESPACE_STD
181
182#endif // _LIBCPP___RANGES_CONCEPTS_H