5 #ifndef VCCC_RANGES_VIEWS_ELEMENTS_VIEW_HPP
6 #define VCCC_RANGES_VIEWS_ELEMENTS_VIEW_HPP
10 #include <type_traits>
50 struct has_tuple_element : std::false_type {};
51 template<
typename T, std::
size_t N>
52 struct has_tuple_element<T, N, true> :
bool_constant<(N < std::tuple_size<T>::value)> {};
54 template<typename T, std::size_t N,
55 bool = std::is_reference<T>::value,
56 bool = has_typename_type<std::tuple_element<N, T>>::value>
57 struct returnable_element : std::false_type {};
58 template<typename T, std::size_t N, bool v>
59 struct returnable_element<T, N, true, v> : std::true_type {};
60 template<typename T, std::size_t N>
61 struct returnable_element<T, N, false, true>
62 : move_constructible<std::tuple_element_t<N, T>> {};
65 template<typename Base, std::size_t N, bool = forward_range<Base>::value >
66 struct elements_view_iterator_category {
67 #if __cplusplus < 202002L
68 using iterator_category = iterator_ignore;
72 template<typename Base, std::size_t N>
73 struct elements_view_iterator_category<Base, N, true> {
75 using C = typename cxx20_iterator_traits<iterator_t<Base>>::iterator_category;
78 using iterator_category =
80 std::is_rvalue_reference<decltype(std::get<N>(*std::declval<iterator_t<Base>&>()))>::value, input_iterator_tag,
82 derived_from<C, random_access_iterator_tag>::value, random_access_iterator_tag,
92 template<typename V, std::size_t N>
93 class elements_view : public view_interface<elements_view<V, N>> {
95 static_assert(input_range<V>::value, "Constraints not satisfied");
96 static_assert(view<V>::value, "Constraints not satisfied");
97 static_assert(detail::has_tuple_element<range_value_t<V>, N>::value, "Constraints not satisfied");
98 static_assert(detail::has_tuple_element<std::remove_reference_t<range_reference_t<V>>, N>::value, "Constraints not satisfied");
99 static_assert(detail::returnable_element<range_reference_t<V>, N>::value, "Constraints not satisfied");
101 template<bool> class iterator;
102 template<bool> class sentinel;
105 class iterator : public detail::elements_view_iterator_category<std::conditional_t<Const, const V, V>, N> {
106 using Base = maybe_const<Const, V>;
107 template<bool> friend class sentinel;
109 template<typename Ref, bool = std::is_reference<Ref>::value >
110 struct iterator_reference {
111 using type = decltype(std::get<N>(*std::declval<iterator_t<Base>&>()));
113 template<typename Ref>
114 struct iterator_reference<Ref, false> {
115 using type = std::remove_cv_t<std::tuple_element_t<N, Ref>>;
119 using iterator_concept =
121 random_access_range<Base>::value, random_access_iterator_tag,
123 bidirectional_range<Base>::value, bidirectional_iterator_tag,
125 forward_range<Base>::value, forward_iterator_tag,
128 using value_type = remove_cvref_t<std::tuple_element_t<N, range_value_t<Base>>>;
129 using difference_type = range_difference_t<Base>;
130 #if __cplusplus < 202002L
131 using pointer = void;
132 using reference = typename iterator_reference<range_reference_t<Base>>::type;
135 iterator() = default;
137 constexpr explicit iterator(iterator_t<Base> current)
138 : current_(std::move(current)) {}
140 template<bool AntiConst, std::enable_if_t<conjunction<
141 bool_constant<((Const != AntiConst) && Const)>,
142 convertible_to<iterator_t<V>, iterator_t<Base>>
144 constexpr iterator(iterator<AntiConst> i)
145 : current_(std::move(i.current_)) {}
147 constexpr const iterator_t<Base>& base() const& noexcept {
151 constexpr iterator_t<Base> base() && {
152 return std::move(current_);
155 constexpr decltype(auto) operator*() const {
156 return get_element(this->base(), std::is_reference<range_reference_t<Base>>{});
159 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
160 constexpr decltype(auto) operator[](difference_type n) const {
161 return get_element(this->base() + n, std::is_reference<range_reference_t<Base>>{});
164 constexpr iterator& operator++() {
169 template<typename B = Base, std::enable_if_t<forward_range<B>::value == false, int> = 0>
170 constexpr void operator++(int) {
174 template<typename B = Base, std::enable_if_t<forward_range<B>::value, int> = 0>
175 constexpr iterator operator++(int) {
181 template<typename B = Base, std::enable_if_t<bidirectional_range<B>::value, int> = 0>
182 constexpr iterator& operator--() {
187 template<typename B = Base, std::enable_if_t<bidirectional_range<B>::value, int> = 0>
188 constexpr iterator operator--(int) {
194 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
195 constexpr iterator& operator+=(difference_type n) {
200 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
201 constexpr iterator& operator-=(difference_type n) {
206 template<typename B = Base, std::enable_if_t<equality_comparable<iterator_t<B>>::value, int> = 0>
207 friend constexpr bool operator==(const iterator& x, const iterator& y) {
208 return x.current_ == y.current_;
211 template<typename B = Base, std::enable_if_t<equality_comparable<iterator_t<B>>::value, int> = 0>
212 friend constexpr bool operator!=(const iterator& x, const iterator& y) {
216 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
217 friend constexpr bool operator<(const iterator& x, const iterator& y) {
218 return x.current_ < y.current_;
221 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
222 friend constexpr bool operator>(const iterator& x, const iterator& y) {
226 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
227 friend constexpr bool operator<=(const iterator& x, const iterator& y) {
231 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
232 friend constexpr bool operator>=(const iterator& x, const iterator& y) {
236 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
237 friend constexpr iterator operator+(iterator i, difference_type n) {
238 return [&](){ auto j = i; j += n; return j; }();
241 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
242 friend constexpr iterator operator+(difference_type n, iterator i) {
243 return [&](){ auto j = i; j += n; return j; }();
246 template<typename B = Base, std::enable_if_t<random_access_range<B>::value, int> = 0>
247 friend constexpr iterator operator-(iterator i, difference_type n) {
248 return [&](){ auto j = i; j -= n; return j; }();
251 template<typename B = Base, std::enable_if_t<sized_sentinel_for<iterator_t<B>, iterator_t<B>>::value, int> = 0>
252 friend constexpr difference_type operator-(const iterator& x, const iterator& y) {
253 return x.current_ - y.current_;
258 constexpr decltype(auto) get_element(T&& e, std::true_type ) const {
259 return std::get<N>(*std::forward<T>(e));
263 constexpr decltype(auto) get_element(T&& e, std::false_type ) const {
264 using E = std::remove_cv_t<std::tuple_element_t<N, range_reference_t<Base>>>;
265 return static_cast<E>(std::get<N>(*std::forward<T>(e)));
268 iterator_t<Base> current_;
273 using Base = maybe_const<Const, V>;
276 sentinel() = default;
278 constexpr explicit sentinel(sentinel_t<Base> end)
279 : end_(std::move(end)) {}
281 template<bool AntiConst, std::enable_if_t<conjunction<
282 bool_constant<((Const != AntiConst) && Const)>,
283 convertible_to<sentinel_t<V>, sentinel_t<Base>>
285 constexpr sentinel(sentinel<AntiConst> i)
286 : end_(std::move(i.end_)) {}
288 constexpr sentinel_t<Base> base() const {
292 template<bool OtherConst, std::enable_if_t<
295 iterator_t<maybe_const<OtherConst, V>>
297 friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y) {
298 using namespace vccc::rel_ops;
299 return x.base() == y.end_;
302 template<bool OtherConst, std::enable_if_t<
305 iterator_t<maybe_const<OtherConst, V>>
307 friend constexpr bool operator!=(const iterator<OtherConst>& x, const sentinel& y) {
311 template<bool OtherConst, std::enable_if_t<
314 iterator_t<maybe_const<OtherConst, V>>
316 friend constexpr bool operator==(const sentinel& y, const iterator<OtherConst>& x) {
320 template<bool OtherConst, std::enable_if_t<
323 iterator_t<maybe_const<OtherConst, V>>
325 friend constexpr bool operator!=(const sentinel& y, const iterator<OtherConst>& x) {
329 template<bool OtherConst, std::enable_if_t<
332 iterator_t<maybe_const<OtherConst, V>>
334 friend constexpr range_difference_t<maybe_const<OtherConst, V>>
335 operator-(const iterator<OtherConst>& x, const sentinel& y) {
336 return x.base() - y.end_;
339 template<bool OtherConst, std::enable_if_t<
342 iterator_t<maybe_const<OtherConst, V>>
344 friend constexpr range_difference_t<maybe_const<OtherConst, V>>
345 operator-(const sentinel& y, const iterator<OtherConst>& x) {
346 return y.end_ - x.base();
351 sentinel_t<Base> end_;
354 elements_view() = default;
356 constexpr explicit elements_view(V base)
357 : base_(std::move(base)) {}
359 template<typename V2 = V, std::enable_if_t<copy_constructible<V2>::value, int> = 0>
360 constexpr V base() const& {
364 constexpr V base() && {
365 return std::move(base_);
368 template<typename V2 = V, std::enable_if_t<simple_view<V2>::value == false, int> = 0>
369 constexpr auto begin() {
370 return iterator<false>{ranges::begin(base_)};
373 template<typename V2 = V, std::enable_if_t<range<const V2>::value, int> = 0>
374 constexpr auto begin() const {
375 return iterator<true>{ranges::begin(base_)};
378 template<typename V2 = V, std::enable_if_t<conjunction<
379 negation< simple_view<V2> >,
380 negation< common_range<V2> >
382 constexpr auto end() {
383 return sentinel<false>{ranges::end(base_)};
386 template<typename V2 = V, std::enable_if_t<conjunction<
387 negation< simple_view<V2> >,
390 constexpr auto end() {
391 return iterator<false>{ranges::end(base_)};
394 template<typename V2 = V, std::enable_if_t<conjunction<
396 negation< common_range<const V2> >
398 constexpr auto end() const {
399 return sentinel<true>{ranges::end(base_)};
402 template<typename V2 = V, std::enable_if_t<conjunction<
403 common_range<const V2>
405 constexpr auto end() const {
406 return iterator<true>{ranges::end(base_)};
409 template<typename V2 = V, std::enable_if_t<sized_range<V2>::value, int> = 0>
410 constexpr auto size() {
411 return ranges::size(base_);
414 template<typename V2 = V, std::enable_if_t<sized_range<const V2>::value, int> = 0>
415 constexpr auto size() const {
416 return ranges::size(base_);
423 template<typename V, std::size_t N>
424 struct enable_borrowed_range<elements_view<V, N>> : enable_borrowed_range<V> {};
std::integral_constant< bool, v > bool_constant
Definition: bool_constant.hpp:19
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35