[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