[libcxx-commits] [libcxx] [libc++][c++23] P2374: `views::cartesian_product` (PR #111215)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Fri Apr 17 23:09:18 PDT 2026


================
@@ -0,0 +1,93 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 explicit cartesian_product_view(First first_base, Vs... bases);
+
+#include <ranges>
+#include <tuple>
+
+#include "../range.zip/types.h"
+
+template <class T>
+void conversion_test(T);
+
+template <class T, class... Args>
+concept implicitly_constructible_from = requires(Args&&... args) { conversion_test<T>({std::move(args)...}); };
+
+// test constructor is explicit
+static_assert(std::constructible_from<std::ranges::cartesian_product_view<SimpleCommon>, SimpleCommon>);
+static_assert(!implicitly_constructible_from<std::ranges::cartesian_product_view<SimpleCommon>, SimpleCommon>);
+
+static_assert(std::constructible_from<std::ranges::cartesian_product_view<SimpleCommon, SimpleCommon>,
+                                      SimpleCommon,
+                                      SimpleCommon>);
+static_assert(!implicitly_constructible_from<std::ranges::cartesian_product_view<SimpleCommon, SimpleCommon>,
+                                             SimpleCommon,
+                                             SimpleCommon>);
+
+struct MoveAwareView : std::ranges::view_base {
+  int moves                 = 0;
+  constexpr MoveAwareView() = default;
+  constexpr MoveAwareView(MoveAwareView&& other) : moves(other.moves + 1) { other.moves = 1; }
+  constexpr MoveAwareView& operator=(MoveAwareView&& other) {
+    moves       = other.moves + 1;
+    other.moves = 0;
+    return *this;
+  }
+  constexpr const int* begin() const { return &moves; }
+  constexpr const int* end() const { return &moves + 1; }
+};
+
+template <class View1, class View2>
+constexpr void constructorTest(auto&& buffer1, auto&& buffer2) {
+  std::ranges::cartesian_product_view v{View1{buffer1}, View2{buffer2}};
+  auto [i, j] = *v.begin();
+  assert(i == buffer1[0]);
+  assert(j == buffer2[0]);
+}
+
+constexpr bool test() {
+  int buffer[]  = {1, 2, 3, 4, 5, 6, 7, 8};
+  int buffer2[] = {9, 8, 7, 6};
+
+  { // constructor from views
+    std::ranges::cartesian_product_view v(
+        SizedRandomAccessView{buffer}, std::views::iota(0), std::ranges::single_view(2.));
+    assert(*v.begin() == std::make_tuple(1, 0, 2.0));
+  }
+
+  { // arguments are moved once
+    MoveAwareView mv;
+    std::ranges::cartesian_product_view v{std::move(mv), MoveAwareView{}};
+    auto [numMoves1, numMoves2] = *v.begin();
+    assert(numMoves1 == 2); // one move from the local variable to parameter, one move from parameter to member
+    assert(numMoves2 == 1);
+  }
+
+  { // input and forward
+    constructorTest<InputCommonView, ForwardSizedView>(buffer, buffer2);
+  }
+
+  { // bidi and random_access
+    constructorTest<BidiCommonView, SizedRandomAccessView>(buffer, buffer2);
+  }
+
+  { // contiguous
+    constructorTest<ContiguousCommonView, ContiguousCommonView>(buffer, buffer2);
+  }
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+  return 0;
+}
----------------
H-G-Hristov wrote:

```suggestion
}

```

+ empty line

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


More information about the libcxx-commits mailing list