[libcxx-commits] [libcxx] [libc++][ranges] Implement `ranges::stride_view`. (PR #65200)
Will Hawkins via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jan 2 19:08:00 PST 2024
================
@@ -0,0 +1,372 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
+
+// constexpr __iterator(__iterator<!_Const> __i)
+// requires _Const && convertible_to<ranges::iterator_t<_View>, iterator_t<_Base>> &&
+// convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
+
+#include <ranges>
+
+#include "../types.h"
+#include "test_iterators.h"
+
+struct NotSimpleViewIterBegin : InputIterBase<NotSimpleViewIterBegin> {};
+
+template <bool CopyConvertible, bool MoveConvertible>
+struct NotSimpleViewConstIterBegin : InputIterBase<NotSimpleViewConstIterBegin<CopyConvertible, MoveConvertible>> {
+ constexpr NotSimpleViewConstIterBegin() = default;
+ constexpr NotSimpleViewConstIterBegin(NotSimpleViewConstIterBegin&&) {}
+ constexpr NotSimpleViewConstIterBegin& operator=(const NotSimpleViewConstIterBegin&) {}
+ constexpr NotSimpleViewConstIterBegin& operator=(NotSimpleViewConstIterBegin&&) {}
+
+ constexpr NotSimpleViewConstIterBegin(const NotSimpleViewConstIterBegin&) {}
+ constexpr NotSimpleViewConstIterBegin(const NotSimpleViewIterBegin&)
+ requires CopyConvertible
+ {}
+ constexpr NotSimpleViewConstIterBegin(NotSimpleViewIterBegin&&)
+ requires MoveConvertible
+ {}
+};
+
+struct NotSimpleViewIterEnd : InputIterBase<NotSimpleViewIterEnd> {};
+
+template <bool CopyConvertible, bool MoveConvertible>
+struct NotSimpleViewConstIterEnd : InputIterBase<NotSimpleViewConstIterEnd<CopyConvertible, MoveConvertible>> {
+ constexpr NotSimpleViewConstIterEnd() = default;
+ constexpr NotSimpleViewConstIterEnd(NotSimpleViewConstIterEnd&&) {}
+ constexpr NotSimpleViewConstIterEnd& operator=(const NotSimpleViewConstIterEnd&) {}
+ constexpr NotSimpleViewConstIterEnd& operator=(NotSimpleViewConstIterEnd&&) {}
+
+ constexpr NotSimpleViewConstIterEnd(const NotSimpleViewConstIterEnd&) {}
+ constexpr NotSimpleViewConstIterEnd(const NotSimpleViewIterEnd&)
+ requires CopyConvertible
+ {}
+ constexpr NotSimpleViewConstIterEnd(NotSimpleViewIterEnd&&)
+ requires MoveConvertible
+ {}
+};
+
+constexpr bool operator==(const NotSimpleViewIterBegin&, const NotSimpleViewIterEnd&) { return true; }
+constexpr bool operator==(const NotSimpleViewIterEnd&, const NotSimpleViewIterBegin&) { return true; }
+
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewConstIterBegin<CopyConvertible, MoveConvertible>&, const NotSimpleViewIterEnd&) {
+ return true;
+}
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewConstIterBegin<CopyConvertible, MoveConvertible>&, const NotSimpleViewIterBegin&) {
+ return true;
+}
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewIterBegin&, const NotSimpleViewConstIterEnd<CopyConvertible, MoveConvertible>&) {
+ return true;
+}
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewIterBegin&, const NotSimpleViewConstIterBegin<CopyConvertible, MoveConvertible>&) {
+ return true;
+}
+
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewConstIterEnd<CopyConvertible, MoveConvertible>&, const NotSimpleViewIterEnd&) {
+ return true;
+}
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewConstIterEnd<CopyConvertible, MoveConvertible>&, const NotSimpleViewIterBegin&) {
+ return true;
+}
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewIterEnd&, const NotSimpleViewConstIterBegin<CopyConvertible, MoveConvertible>&) {
+ return true;
+}
+template <bool CopyConvertible, bool MoveConvertible>
+constexpr bool
+operator==(const NotSimpleViewIterEnd&, const NotSimpleViewConstIterEnd<CopyConvertible, MoveConvertible>&) {
+ return true;
+}
+
+/*
+ * Goal: We will need a way to get a stride_view<true>::__iterator and a
+ * stride_view<false>::__iterator because those are the two possible types
+ * of the stride_view::__iterator constructor. The template value is determined
+ * by whether the stride_view::__iterator is derivative of a stride_view over a
+ * view that is simple.
+ *
+ * So, first things first, we need to build a stride_view over a (non-)simple view.
+ * There are (at least) two ways that a view can be non-simple:
+ * 1. The iterator type for const begin is different than the iterator type for begin
+ * 2. The iterator type for const end is different that the iterator type for end
+ *
+ * So, let's create two different classes where that is the case so that we can test
+ * for those conditions individually. We parameterize with a template to decide
+ * whether to
+ * 1. enable converting constructors between the non-const and the const version.
+ * That feature is important for testing the stride_view::__iterator<true> converting
+ * constructor from a stride_view::_iterator<false> iterator.
+ * 2. enable copyability. That feature is important for testing whether the requirement
+ * the that copy constructor for the stride_view::__iterator<false> type actually moves
+ * the underlying iterator.
+ */
+template <bool CopyConvertible = false, bool MoveConvertible = true>
+struct NotSimpleViewDifferentBegin : std::ranges::view_base {
+ constexpr NotSimpleViewConstIterBegin<CopyConvertible, MoveConvertible> begin() const { return {}; }
+ constexpr NotSimpleViewIterBegin begin() { return {}; }
+
+ constexpr NotSimpleViewIterEnd end() const { return {}; }
+};
+
+template <bool CopyConvertible = false, bool MoveConvertible = true>
+struct NotSimpleViewDifferentEnd : std::ranges::view_base {
+ constexpr NotSimpleViewIterBegin begin() const { return {}; }
+ constexpr NotSimpleViewConstIterEnd<CopyConvertible, MoveConvertible> end() const { return {}; }
+ constexpr NotSimpleViewIterEnd end() { return {}; }
+};
+
+constexpr bool non_simple_view_iter_ctor_test() {
+ using NotSimpleStrideView = std::ranges::stride_view<NotSimpleViewDifferentBegin<false>>;
+ using NotSimpleStrideViewIter = std::ranges::iterator_t<NotSimpleStrideView>;
+ using NotSimpleStrideViewIterConst = std::ranges::iterator_t<const NotSimpleStrideView>;
+ static_assert(!std::is_same_v<NotSimpleStrideViewIterConst, NotSimpleStrideViewIter>);
+ return true;
+}
+
+constexpr bool non_const_iterator_copy_ctor() {
+ // All tests share the following general configuration.
+ //
+ // Instantiate a stride view StrideView over a non-simple view (NotSimpleViewBeingStrided) whose
+ // 1. std::ranges::iterator_t<StrideView> base's type is NotSimpleViewBeingStridedIterator
+ // 2. std::ranges::iterator_t<const StrideView> base's type is NotSimpleViewBeingStridedConstIterator
+ // 3. NotSimpleViewBeingStridedIterator is ONLY move-convertible to NotSimpleViewBeingStridedConstIterator
+ // 4. std::ranges::sentinel_t are the same whether SV is const or not.
+ // 4. the type of StrideView::end is the same whether StrideView is const or not.
+ // 5. the type of StrideView::begin is stride_view::iterator<true> when StrideView is const and
----------------
hawkinsw wrote:
Great eyes!
https://github.com/llvm/llvm-project/pull/65200
More information about the libcxx-commits
mailing list