[libcxx-commits] [libcxx] [libc++][ranges] Implement `ranges::stride_view`. (PR #65200)
Konstantin Varlamov via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Oct 2 20:44:19 PDT 2023
================
@@ -0,0 +1,413 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_STRIDE_VIEW_H
+#define _LIBCPP___RANGES_STRIDE_VIEW_H
+
+#include <__config>
+
+#include <__compare/three_way_comparable.h>
+#include <__concepts/constructible.h>
+#include <__concepts/convertible_to.h>
+#include <__concepts/derived_from.h>
+#include <__functional/bind_back.h>
+#include <__iterator/advance.h>
+#include <__iterator/concepts.h>
+#include <__iterator/default_sentinel.h>
+#include <__iterator/distance.h>
+#include <__iterator/iter_move.h>
+#include <__iterator/iter_swap.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/next.h>
+#include <__ranges/access.h>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/non_propagating_cache.h>
+#include <__ranges/range_adaptor.h>
+#include <__ranges/size.h>
+#include <__ranges/subrange.h>
+#include <__ranges/view_interface.h>
+#include <__ranges/views.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/maybe_const.h>
+#include <__type_traits/remove_cvref.h>
+#include <__utility/forward.h>
+#include <__utility/move.h>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 23
+
+namespace ranges {
+
+template <class _Value>
+_LIBCPP_HIDE_FROM_ABI constexpr _Value __div_ceil(_Value __left, _Value __right) {
+ _Value __r = __left / __right;
+ if (__left % __right) {
+ __r++;
+ }
+ return __r;
+}
+
+template <input_range _View>
+ requires view<_View>
+class stride_view : public view_interface<stride_view<_View>> {
+ _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
+ range_difference_t<_View> __stride_ = 0;
+
+ template <bool _Const>
+ class __iterator;
+
+public:
+ _LIBCPP_HIDE_FROM_ABI constexpr explicit stride_view(_View __base, range_difference_t<_View> __stride)
+ : __base_(std::move(__base)), __stride_(__stride) {}
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _View base() const&
+ requires copy_constructible<_View>
+ {
+ return __base_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr range_difference_t<_View> stride() const noexcept { return __stride_; }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto size()
+ requires sized_range<_View>
+ {
+ return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __stride_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
+ requires sized_range<const _View>
+ {
+ return std::__to_unsigned_like(ranges::__div_ceil(ranges::distance(__base_), __stride_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto begin()
+ requires(!__simple_view<_View>)
+ {
+ return __iterator<false>{*this, ranges::begin(__base_)};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const
+ requires range<const _View>
+ {
+ return __iterator<true>{*this, ranges::begin(__base_)};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+ requires(!__simple_view<_View> && common_range<_View> && sized_range<_View> && forward_range<_View>)
+ {
+ auto __missing = (__stride_ - ranges::distance(__base_) % __stride_) % __stride_;
+ return __iterator<false>{*this, ranges::end(__base_), __missing};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+ requires(!__simple_view<_View> && common_range<_View> && !bidirectional_range<_View>)
+ {
+ return __iterator<false>{*this, ranges::end(__base_)};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end()
+ requires(!__simple_view<_View>)
+ {
+ return std::default_sentinel;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ requires(range<const _View> && common_range<const _View> && sized_range<const _View> && forward_range<const _View>)
+ {
+ auto __missing = (__stride_ - ranges::distance(__base_) % __stride_) % __stride_;
+ return __iterator<true>{*this, ranges::end(__base_), __missing};
+ }
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ requires(range<const _View> && common_range<_View> && !bidirectional_range<_View>)
+ {
+ return __iterator<true>{*this, ranges::end(__base_)};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr auto end() const
+ requires(range<const _View>)
+ {
+ return std::default_sentinel;
+ }
+}; // class stride_view
+
+template <class _View>
+struct __stride_view_iterator_concept {
+ using type = input_iterator_tag;
+};
+
+template <random_access_range _View>
+struct __stride_view_iterator_concept<_View> {
+ using type = random_access_iterator_tag;
+};
+
+template <bidirectional_range _View>
+struct __stride_view_iterator_concept<_View> {
+ using type = bidirectional_iterator_tag;
+};
+
+template <forward_range _View>
+struct __stride_view_iterator_concept<_View> {
+ using type = forward_iterator_tag;
+};
+
+template <class _View>
+struct __stride_iterator_category {};
+
+template <forward_range _View>
+struct __stride_iterator_category<_View> {
+ using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category;
+ using iterator_category =
+ _If<derived_from<_Cat, random_access_iterator_tag>,
+ random_access_iterator_tag,
+ /* else */ _Cat >;
+};
+
+template <input_range _View>
+ requires view<_View>
+template <bool _Const>
+class stride_view<_View>::__iterator : public __stride_iterator_category<_View> {
+ using _Parent = __maybe_const<_Const, stride_view<_View>>;
+ using _Base = __maybe_const<_Const, _View>;
+
+ _LIBCPP_NO_UNIQUE_ADDRESS iterator_t<_Base> __current_ = iterator_t<_Base>();
+ _LIBCPP_NO_UNIQUE_ADDRESS ranges::sentinel_t<_Base> __end_ = ranges::sentinel_t<_Base>();
+ range_difference_t<_Base> __stride_ = 0;
+ range_difference_t<_Base> __missing_ = 0;
+
+ friend stride_view;
+
+public:
+ using difference_type = range_difference_t<_Base>;
+ using value_type = range_value_t<_Base>;
+ using iterator_concept = typename __stride_view_iterator_concept<_View>::type;
+
+ // using iterator_category = inherited;
----------------
var-const wrote:
Nit: can you move this comment one line up so that it's the last line of the previous block? It should be grouped with the other aliases, not with the constructor.
https://github.com/llvm/llvm-project/pull/65200
More information about the libcxx-commits
mailing list