[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,234 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 auto end();
+// constexpr auto end() const
+//   requires forward_range<const V> && forward_range<const Pattern> &&
+//            is_reference_v<range_reference_t<const V>> &&
+//            input_range<range_reference_t<const V>>;
+
+// ADDITIONAL_COMPILE_FLAGS(has-fconstexpr-steps): -fconstexpr-steps=10000000
+
+#include <ranges>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include "../types.h"
+#include "test_iterators.h"
+
+template <class V, class Pattern>
+concept JoinWithViewHasConstEnd = requires(const std::ranges::join_with_view<V, Pattern> jwv) { jwv.end(); };
+
+template <size_t Bits>
+  requires(Bits < (1 << 7))
+constexpr void test_end() {
+  constexpr bool v_models_forward_range           = Bits & (1 << 0);
+  constexpr bool inner_range_is_reference         = Bits & (1 << 1);
+  constexpr bool inner_range_models_forward_range = Bits & (1 << 2);
+  constexpr bool v_models_common_range            = Bits & (1 << 3);
+  constexpr bool inner_range_models_common_range  = Bits & (1 << 4);
+  constexpr bool v_models_simple_range            = Bits & (1 << 5);
+  constexpr bool pattern_models_simple_range      = Bits & (1 << 6);
+
+  constexpr ViewProperties inner_range_props{.common = inner_range_models_common_range};
+  using InnerRange =
+      std::conditional_t<inner_range_models_forward_range,
+                         BasicView<std::vector<int>, inner_range_props, forward_iterator>,
+                         BasicView<std::vector<int>, inner_range_props, DefaultCtorInputIter>>;
+
+  constexpr ViewProperties v_props{.simple = v_models_simple_range, .common = v_models_common_range};
+  using UnderlyingV = std::conditional_t<inner_range_is_reference, std::vector<InnerRange>, RvalueVector<InnerRange>>;
+  using V           = std::conditional_t<v_models_forward_range,
+                                         BasicView<UnderlyingV, v_props, forward_iterator>,
+                                         BasicView<UnderlyingV, v_props, DefaultCtorInputIter>>;
+
+  using UnderlyingPattern = std::vector<int>;
+  using Pattern = BasicView<UnderlyingPattern, ViewProperties{.simple = pattern_models_simple_range}, forward_iterator>;
+
+  using JWV  = std::ranges::join_with_view<V, Pattern>;
+  using Iter = std::ranges::iterator_t<JWV>;
+
+  // Test when `JWV` models common range
+  static_assert(std::same_as<Iter, std::ranges::sentinel_t<JWV>> ==
+                (v_models_forward_range && inner_range_is_reference && inner_range_models_forward_range &&
+                 v_models_common_range && inner_range_models_common_range));
+
+  { // `V` and `Pattern` are empty
+    V v{};
+    Pattern pattern{};
+    JWV jwv(std::move(v), std::move(pattern));
+    Iter it                                   = jwv.begin();
+    std::sentinel_for<Iter> decltype(auto) se = jwv.end();
+    assert(it == se);
+  }
+
+  { // `V` is empty, `Pattern` contains some elements
+    V v{};
+    Pattern pattern{std::vector<int>{0}};
+    JWV jwv(std::move(v), std::move(pattern));
+    Iter it                                   = jwv.begin();
+    std::sentinel_for<Iter> decltype(auto) se = jwv.end();
+    assert(it == se);
+  }
+
+  { // `V` is not empty, `Pattern is empty`
+    V v{UnderlyingV{
+        std::vector<InnerRange>{InnerRange(std::vector<int>{1, 2, 3}), InnerRange(std::vector<int>{4, 5, 6})}}};
+    Pattern pattern{};
+    JWV jwv(std::move(v), std::move(pattern));
+    Iter it                                   = jwv.begin();
+    std::sentinel_for<Iter> decltype(auto) se = jwv.end();
+    assert(std::ranges::next(it, 6) == se);
+  }
+
+  { // `V` and `Pattern` are not empty
+    V v{UnderlyingV{std::vector<InnerRange>{
+        InnerRange(std::vector<int>{6, 5}),
+        InnerRange(std::vector<int>{4, 3}),
+        InnerRange(std::vector<int>{2, 1, 0})}}};
+    Pattern pattern{std::vector<int>{-1, -1}};
+    JWV jwv(std::move(v), std::move(pattern));
+    Iter it                                   = jwv.begin();
+    std::sentinel_for<Iter> decltype(auto) se = jwv.end();
+    assert(std::ranges::next(it, 11) == se);
+  }
+}
+
+constexpr void test_end() {}
----------------
huixie90 wrote:

why is this needed?

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


More information about the libcxx-commits mailing list