[libcxx-commits] [libcxx] [libc++] Implement `views::join_with` (PR #65536)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 26 07:20:16 PST 2024


================
@@ -0,0 +1,320 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// <ranges>
+
+// constexpr iterator& operator++();
+// constexpr void operator++(int);
+// constexpr iterator operator++(int)
+//   requires ref-is-glvalue && forward_iterator<OuterIter> &&
+//            forward_iterator<InnerIter>;
+
+#include <ranges>
+
+#include <array>
+#include <cassert>
+#include <type_traits>
+#include <vector>
+
+#include "../types.h"
+
+template <class I>
+concept CanPreIncrement = requires(I& i) { ++i; };
+
+template <class I>
+concept CanPostIncrement = requires(I& i) { i++; };
+
+constexpr void test_pre_increment() {
+  { // `V` and `Pattern` are not empty. Test return type too.
+    using V       = std::array<std::array<int, 2>, 3>;
+    using Pattern = std::array<int, 2>;
+    using JWV     = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
+
+    using Iter  = std::ranges::iterator_t<JWV>;
+    using CIter = std::ranges::iterator_t<const JWV>;
+    static_assert(CanPreIncrement<Iter>);
+    static_assert(!CanPreIncrement<const Iter>);
+    static_assert(CanPreIncrement<CIter>);
+    static_assert(!CanPreIncrement<const CIter>);
+
+    JWV jwv(V{{{1, 1}, {2, 2}, {3, 3}}}, Pattern{0, 0});
+
+    {
+      auto it = jwv.begin();
+      assert(*it == 1);
+      std::same_as<Iter&> decltype(auto) it_ref = ++it;
+      assert(it_ref == it);
+      ++it;
+      assert(*it == 0);
+      ++it_ref;
+      ++it_ref;
+      assert(*it_ref == 2);
+      ++it;
+      ++it_ref;
+      assert(*it == 0);
+    }
+
+    {
+      auto cit = std::as_const(jwv).begin();
+      assert(*cit == 1);
+      std::same_as<CIter&> decltype(auto) cit_ref = ++cit;
+      assert(cit_ref == cit);
+      ++cit;
+      assert(*cit == 0);
+      ++cit_ref;
+      ++cit_ref;
+      assert(*cit_ref == 2);
+      ++cit;
+      ++cit_ref;
+      assert(*cit == 0);
+    }
+  }
+
+#if !defined(TEST_COMPILER_GCC) // GCC c++/101777
+
+  { // `Pattern` is empty, `V` is not.
+    using V       = std::array<std::vector<int>, 3>;
+    using Pattern = std::vector<int>;
+    using JWV     = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>;
+
+    JWV jwv(V{{{-1}, {-2}, {-3}}}, Pattern{});
+
+    {
+      auto it = jwv.begin();
+      assert(*it == -1);
+      ++it;
+      assert(*it == -2);
+      ++it;
+      assert(*it == -3);
+      ++it;
+      assert(it == jwv.end());
+    }
+
+    {
+      auto cit = std::as_const(jwv).begin();
+      assert(*cit == -1);
+      ++cit;
+      assert(*cit == -2);
+      ++cit;
+      assert(*cit == -3);
+      ++cit;
+      assert(cit == std::as_const(jwv).end());
+    }
+  }
+
+  { // `V` has empty subrange in the middle, `Pattern` is not empty.
+    using V       = std::array<std::vector<int>, 3>;
+    using Pattern = std::ranges::single_view<int>;
+    using JWV     = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;
+
+    JWV jwv(V{{{1}, {}, {3}}}, Pattern{0});
+
+    {
+      auto it = jwv.begin();
+      assert(*it == 1);
+      ++it;
+      assert(*it == 0);
+      ++it;
+      assert(*it == 0);
+      ++it;
+      assert(*it == 3);
+    }
+
+    {
+      auto cit = std::as_const(jwv).begin();
+      assert(*cit == 1);
+      ++cit;
+      assert(*cit == 0);
+      ++cit;
+      assert(*cit == 0);
+      ++cit;
+      assert(*cit == 3);
+    }
+  }
+
+  { // Only first element of `V` is not empty. `Pattern` is empty.
+    using V       = std::array<std::vector<int>, 3>;
+    using Pattern = std::ranges::empty_view<int>;
+    using JWV     = std::ranges::join_with_view<std::ranges::owning_view<V>, Pattern>;
+
+    JWV jwv(V{{{777}, {}, {}}}, Pattern{});
+
+    {
+      auto it = jwv.begin();
+      assert(*it == 777);
+      ++it;
+      assert(it == jwv.end());
+    }
+
+    {
+      auto cit = std::as_const(jwv).begin();
+      assert(*cit == 777);
+      ++cit;
+      assert(cit == std::as_const(jwv).end());
+    }
+  }
+
+#endif // !defined(TEST_COMPILER_GCC)
+
+  { // Only last element of `V` is not empty. `Pattern` is empty. `V` models input range and `ref-is-glvalue` is false.
----------------
huixie90 wrote:

I wonder if you can parameterise the test on `ref-is-glvalue` is true/false and test all the combinations of the emptiness of V and Pattern.

https://github.com/llvm/llvm-project/pull/65536


More information about the libcxx-commits mailing list