Skip to content

[libc++][ranges] P2542R8: Implement views::concat #120920

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 151 commits into
base: main
Choose a base branch
from

Conversation

changkhothuychung
Copy link
Contributor

@changkhothuychung changkhothuychung commented Dec 22, 2024

Closes #105419
Closes #105348
Closes #105349

@changkhothuychung changkhothuychung requested a review from a team as a code owner December 22, 2024 21:29
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 22, 2024
@changkhothuychung changkhothuychung marked this pull request as draft December 22, 2024 21:29
@llvmbot
Copy link
Member

llvmbot commented Dec 22, 2024

@llvm/pr-subscribers-libcxx

Author: Nhat Nguyen (changkhothuychung)

Changes

Patch is 52.01 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/120920.diff

14 Files Affected:

  • (added) libcxx/include/__ranges/concat_view.h (+624)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/adaptor.pass.cpp (+71)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp (+38)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/ctad.pass.cpp (+54)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp (+81)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp (+70)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/end.pass.cpp (+99)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/iterator/compare.pass.cpp (+76)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/iterator/decrement.pass.cpp (+89)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/iterator/deref.pass.cpp (+56)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/iterator/increment.pass.cpp (+84)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_move.pass.cpp (+74)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_swap.pass.cpp (+79)
  • (added) libcxx/test/std/ranges/range.adaptors/range.concat/types.h (+44)
diff --git a/libcxx/include/__ranges/concat_view.h b/libcxx/include/__ranges/concat_view.h
new file mode 100644
index 00000000000000..9d17aae65ecaf5
--- /dev/null
+++ b/libcxx/include/__ranges/concat_view.h
@@ -0,0 +1,624 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_CONCAT_VIEW_H
+#define _LIBCPP___RANGES_CONCAT_VIEW_H
+
+#include <__algorithm/ranges_find_if.h>
+#include <__assert>
+#include <__concepts/constructible.h>
+#include <__concepts/copyable.h>
+#include <__concepts/derived_from.h>
+#include <__concepts/equality_comparable.h>
+#include <__config>
+#include <__functional/bind_back.h>
+#include <__functional/invoke.h>
+#include <__functional/reference_wrapper.h>
+#include <__iterator/concepts.h>
+#include <__iterator/default_sentinel.h>
+#include <__iterator/distance.h>
+#include <__iterator/iter_move.h>
+#include <__iterator/iter_swap.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/next.h>
+#include <__memory/addressof.h>
+#include <__ranges/access.h>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/movable_box.h>
+#include <__ranges/non_propagating_cache.h>
+#include <__ranges/range_adaptor.h>
+#include <__ranges/view_interface.h>
+#include <__type_traits/conditional.h>
+#include <__type_traits/decay.h>
+#include <__type_traits/is_nothrow_constructible.h>
+#include <__type_traits/is_nothrow_convertible.h>
+#include <__type_traits/is_object.h>
+#include <__type_traits/maybe_const.h>
+#include <__utility/forward.h>
+#include <__utility/in_place.h>
+#include <__utility/move.h>
+#include <tuple>
+#include <variant>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER >= 20
+
+namespace ranges {
+
+template <class T, class... Ts>
+struct extract_last : extract_last<Ts...> {};
+
+template <class T>
+struct extract_last<T> {
+  using type = T;
+};
+
+template <class _T, class... _Ts>
+struct derived_from_pack {
+  constexpr static bool value =
+      derived_from_pack<_T, typename extract_last<_Ts...>::type>::value && derived_from_pack<_Ts...>::value;
+};
+
+template <class _T, class _IterCategory>
+struct derived_from_pack<_T, _IterCategory> {
+  constexpr static bool value = derived_from<_T, _IterCategory>;
+};
+
+template <class View, class... Views>
+struct last_view : last_view<Views...> {};
+
+template <class View>
+struct last_view<View> {
+  using type = View;
+};
+
+template <class Ref, class RRef, class It>
+concept concat_indirectly_readable_impl = requires(const It it) {
+  { *it } -> convertible_to<Ref>;
+  { ranges::iter_move(it) } -> convertible_to<RRef>;
+};
+
+template <class... Rs>
+using concat_reference_t = common_reference_t<range_reference_t<Rs>...>;
+
+template <class... Rs>
+using concat_value_t = common_type_t<range_value_t<Rs>...>;
+
+template <class... Rs>
+using concat_rvalue_reference_t = common_reference_t<range_rvalue_reference_t<Rs>...>;
+
+template <class... Rs>
+concept concat_indirectly_readable =
+    common_reference_with<concat_reference_t<Rs...>&&, concat_value_t<Rs...>&> &&
+    common_reference_with<concat_reference_t<Rs...>&&, concat_rvalue_reference_t<Rs...>&&> &&
+    common_reference_with<concat_rvalue_reference_t<Rs...>&&, concat_value_t<Rs...> const&> &&
+    (concat_indirectly_readable_impl<concat_reference_t<Rs...>, concat_rvalue_reference_t<Rs...>, iterator_t<Rs>> &&
+     ...);
+
+template <class... Rs>
+concept concatable = requires { // exposition only
+  typename concat_reference_t<Rs...>;
+  typename concat_value_t<Rs...>;
+  typename concat_rvalue_reference_t<Rs...>;
+} && concat_indirectly_readable<Rs...>;
+
+template <bool Const, class... Rs>
+concept concat_is_random_access =
+    (random_access_range<__maybe_const<Const, Rs>> && ...) && (sized_range<__maybe_const<Const, Rs>> && ...);
+
+template <class R>
+concept constant_time_reversible = // exposition only
+    (bidirectional_range<R> && common_range<R>) || (sized_range<R> && random_access_range<R>);
+
+template <bool Const, class... Rs>
+concept concat_is_bidirectional =
+    ((bidirectional_range<__maybe_const<Const, Rs>> && ...) &&
+     (constant_time_reversible<__maybe_const<Const, Rs>> && ...));
+
+template <bool Const, class... Views>
+concept all_forward = // exposition only
+    (forward_range<__maybe_const<Const, Views>> && ...);
+
+template <bool Const, class... Ts>
+struct apply_drop_first;
+
+template <bool Const, class Head, class... Tail>
+struct apply_drop_first<Const, Head, Tail...> {
+  static constexpr bool value = (sized_range<__maybe_const<Const, Tail>> && ...);
+};
+
+template <input_range... Views>
+  requires(view<Views> && ...) && (sizeof...(Views) > 0) && concatable<Views...>
+class concat_view : public view_interface<concat_view<Views...>> {
+  tuple<Views...> views_;
+
+  template <bool Const>
+  class iterator;
+  class sentinel;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI constexpr concat_view() = default;
+
+  _LIBCPP_HIDE_FROM_ABI constexpr explicit concat_view(Views... views) : views_(std::move(views)...) {}
+
+  constexpr iterator<false> begin()
+    requires(!(__simple_view<Views> && ...))
+  {
+    iterator<false> it(this, in_place_index<0>, ranges::begin(get<0>(views_)));
+    it.template satisfy<0>();
+    return it;
+  }
+
+  constexpr iterator<true> begin() const
+    requires((range<const Views> && ...) && concatable<const Views...>)
+  {
+    iterator<true> it(this, in_place_index<0>, ranges::begin(get<0>(views_)));
+    it.template satisfy<0>();
+    return it;
+  }
+
+  constexpr auto end()
+    requires(!(__simple_view<Views> && ...))
+  {
+    if constexpr (common_range<typename last_view<Views...>::type>) {
+      // last_view to be implemented
+      constexpr auto N = sizeof...(Views);
+      return iterator<false>(this, in_place_index<N - 1>, ranges::end(get<N - 1>(views_)));
+    } else {
+      return default_sentinel;
+    }
+  }
+
+  constexpr auto end() const
+    requires(range<const Views> && ...)
+  {
+    if constexpr (common_range<typename last_view<Views...>::type>) {
+      // last_view to be implemented
+      constexpr auto N = sizeof...(Views);
+      return iterator<true>(this, in_place_index<N - 1>, ranges::end(get<N - 1>(views_)));
+    } else {
+      return default_sentinel;
+    }
+  }
+
+  constexpr auto size()
+    requires(sized_range<Views> && ...)
+  {
+    return apply(
+        [](auto... sizes) {
+          using CT = make_unsigned_t<common_type_t<decltype(sizes)...>>;
+          return (CT(sizes) + ...);
+        },
+        tuple_transform(ranges::size, views_));
+  }
+
+  constexpr auto size() const
+    requires(sized_range<const Views> && ...)
+  {
+    return apply(
+        [](auto... sizes) {
+          using CT = make_unsigned_t<common_type_t<decltype(sizes)...>>;
+          return (CT(sizes) + ...);
+        },
+        tuple_transform(ranges::size, views_));
+  }
+};
+
+template <class... _Views>
+concat_view(_Views&&...) -> concat_view<views::all_t<_Views>...>;
+
+template <input_range... Views>
+  requires(view<Views> && ...) && (sizeof...(Views) > 0) && concatable<Views...>
+template <bool Const>
+class concat_view<Views...>::iterator {
+public:
+  constexpr static bool derive_pack_random_iterator =
+      derived_from_pack<typename iterator_traits<iterator_t<__maybe_const<Const, Views>>>::iterator_category...,
+                        random_access_iterator_tag>::value;
+  constexpr static bool derive_pack_bidirectional_iterator =
+      derived_from_pack<typename iterator_traits<iterator_t<__maybe_const<Const, Views>>>::iterator_category...,
+                        bidirectional_iterator_tag>::value;
+  constexpr static bool derive_pack_forward_iterator =
+      derived_from_pack<typename iterator_traits< iterator_t<__maybe_const<Const, Views>>>::iterator_category...,
+                        forward_iterator_tag>::value;
+  using iterator_category =
+      _If<!is_reference_v<concat_reference_t<__maybe_const<Const, Views>...>>,
+          input_iterator_tag,
+          _If<derive_pack_random_iterator,
+              random_access_iterator_tag,
+              _If<derive_pack_bidirectional_iterator,
+                  bidirectional_iterator_tag,
+                  _If<derive_pack_forward_iterator, forward_iterator_tag, input_iterator_tag > > > >;
+  using iterator_concept =
+      _If<concat_is_random_access<Const, Views...>,
+          random_access_iterator_tag,
+          _If<concat_is_bidirectional<Const, Views...>,
+              bidirectional_iterator_tag,
+              _If< all_forward<Const, Views...>, forward_iterator_tag, input_iterator_tag > > >;
+  using value_type      = concat_value_t<__maybe_const<Const, Views>...>;
+  using difference_type = common_type_t<range_difference_t<__maybe_const<Const, Views>>...>;
+  using base_iter       = variant<iterator_t<__maybe_const<Const, Views>>...>;
+
+  base_iter it_;                                        // exposition only
+  __maybe_const<Const, concat_view>* parent_ = nullptr; // exposition only
+
+  template <std::size_t N>
+  constexpr void satisfy() {
+    if constexpr (N < (sizeof...(Views) - 1)) {
+      if (get<N>(it_) == ranges::end(get<N>(parent_->views_))) {
+        it_.template emplace<N + 1>(ranges::begin(get<N + 1>(parent_->views_)));
+        satisfy<N + 1>();
+      }
+    }
+  }
+
+  template <std::size_t N>
+  constexpr void prev() {
+    if constexpr (N == 0) {
+      --get<0>(it_);
+    } else {
+      if (get<N>(it_) == ranges::begin(get<N>(parent_->views_))) {
+        using prev_view = __maybe_const<Const, tuple_element_t<N - 1, tuple<Views...>>>;
+        if constexpr (common_range<prev_view>) {
+          it_.emplace<N - 1>(ranges::end(get<N - 1>(parent_->views_)));
+        } else {
+          it_.emplace<N - 1>(
+              ranges::__next(ranges::begin(get<N - 1>(parent_->views_)), ranges::size(get<N - 1>(parent_->views_))));
+        }
+        prev<N - 1>();
+      } else {
+        --get<N>(it_);
+      }
+    }
+  }
+
+  template <std::size_t N>
+  constexpr void advance_fwd(difference_type offset, difference_type steps) {
+    using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base_iter>>;
+    if constexpr (N == sizeof...(Views) - 1) {
+      get<N>(it_) += static_cast<underlying_diff_type>(steps);
+    } else {
+      difference_type n_size = ranges::size(get<N>(parent_->views_));
+      if (offset + steps < n_size) {
+        get<N>(it_) += static_cast<underlying_diff_type>(steps);
+      } else {
+        it_.template emplace<N + 1>(ranges::begin(get<N + 1>(parent_->views_)));
+        advance_fwd<N + 1>(0, offset + steps - n_size);
+      }
+    }
+  }
+
+  template <std::size_t N>
+  constexpr void advance_bwd(difference_type offset, difference_type steps) {
+    using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base_iter>>;
+    if constexpr (N == 0) {
+      get<N>(it_) -= static_cast<underlying_diff_type>(steps);
+    } else {
+      if (offset >= steps) {
+        get<N>(it_) -= static_cast<underlying_diff_type>(steps);
+      } else {
+        auto prev_size = ranges::__distance(get<N - 1>(parent_->views_));
+        it_.emplace<N - 1>(ranges::begin(get<N - 1>(parent_->views_)) + prev_size);
+        advance_bwd<N - 1>(prev_size, steps - offset);
+      }
+    }
+  }
+
+  template <size_t... Is, typename Func>
+  constexpr void apply_fn_with_const_index(size_t index, Func&& func, std::index_sequence<Is...>) {
+    ((index == Is ? (func(std::integral_constant<size_t, Is>{}), 0) : 0), ...);
+  }
+
+  template <size_t N, typename Func>
+  constexpr void apply_fn_with_const_index(size_t index, Func&& func) {
+    apply_fn_with_const_index(index, std::forward<Func>(func), std::make_index_sequence<N>{});
+  }
+
+  template <class... Args>
+  explicit constexpr iterator(__maybe_const<Const, concat_view>* parent, Args&&... args)
+    requires constructible_from<base_iter, Args&&...>
+      : it_(std::forward<Args>(args)...), parent_(parent) {}
+
+public:
+  iterator() = default;
+
+  constexpr iterator(iterator<!Const> i)
+    requires Const && (convertible_to<iterator_t<Views>, iterator_t<const Views>> && ...)
+      : it_(base_iter(in_place_index<i.index()>, std::get<i.index()>(std::move(i.it_)))), parent_(i.parent_) {}
+
+  constexpr decltype(auto) operator*() const {
+    using reference = concat_reference_t<__maybe_const<Const, Views>...>;
+    return std::visit([](auto&& it) -> reference { return *it; }, it_);
+  }
+
+  constexpr iterator& operator++() {
+    size_t active_index = it_.index();
+    apply_fn_with_const_index<std::variant_size_v<decltype(it_)>>(active_index, [&](auto index_constant) {
+      constexpr size_t i = index_constant.value;
+      ++get<i>(it_);
+      satisfy<i>();
+    });
+    return *this;
+  }
+
+  constexpr void operator++(int) { ++*this; }
+
+  constexpr iterator operator++(int)
+    requires(forward_range<__maybe_const<Const, Views>> && ...)
+  {
+    auto tmp = *this;
+    ++*this;
+    return tmp;
+  }
+
+  constexpr iterator& operator--()
+    requires concat_is_bidirectional<Const, Views...>
+  {
+    size_t active_index = it_.index();
+    apply_fn_with_const_index<std::variant_size_v<decltype(it_)>>(active_index, [&](auto index_constant) {
+      constexpr size_t i = index_constant.value;
+      prev<i>();
+    });
+    return *this;
+  }
+
+  constexpr iterator operator--(int)
+    requires concat_is_bidirectional<Const, Views...>
+  {
+    auto __tmp = *this;
+    --*this;
+    return __tmp;
+  }
+
+  friend constexpr bool operator==(const iterator& x, const iterator& y)
+    requires(equality_comparable<iterator_t<__maybe_const<Const, Views>>> && ...)
+  {
+    return x.it_ == y.it_;
+  }
+
+  constexpr decltype(auto) operator[](difference_type n) const
+    requires concat_is_random_access<Const, Views...>
+  {
+    return *((*this) + n);
+  }
+
+  friend constexpr iterator operator+(const iterator& it, difference_type n)
+    requires concat_is_random_access<Const, Views...>
+  {
+    auto temp = it;
+    temp += n;
+    return temp;
+  }
+
+  friend constexpr iterator operator+(difference_type n, const iterator& it)
+    requires concat_is_random_access<Const, Views...>
+  {
+    return it + n;
+  }
+
+  constexpr iterator& operator+=(difference_type n)
+    requires concat_is_random_access<Const, Views...>
+  {
+    size_t active_index = it_.index();
+    if (n > 0) {
+      std::visit(
+          [&](auto& active_it) {
+            apply_fn_with_const_index<std::tuple_size_v<decltype(parent_->views_)>>(
+                active_index, [&](auto index_constant) {
+                  constexpr size_t I  = index_constant.value;
+                  auto& active_view   = std::get<I>(parent_->views_);
+                  difference_type idx = active_it - ranges::begin(active_view);
+                  advance_fwd<I>(idx, n);
+                });
+          },
+          it_);
+    }
+
+    else if (n < 0) {
+      std::visit(
+          [&](auto& active_it) {
+            apply_fn_with_const_index<std::tuple_size_v<decltype(parent_->views_)>>(
+                active_index, [&](auto index_constant) {
+                  constexpr size_t I  = index_constant.value;
+                  auto& active_view   = std::get<I>(parent_->views_);
+                  difference_type idx = active_it - ranges::begin(active_view);
+                  advance_bwd<I>(idx, -n);
+                });
+          },
+          it_);
+    }
+
+    return *this;
+  }
+
+  constexpr iterator& operator-=(difference_type n)
+    requires concat_is_random_access<Const, Views...>
+  {
+    *this += -n;
+    return *this;
+  }
+
+  friend constexpr bool operator==(const iterator& it, default_sentinel_t) {
+    constexpr auto last_idx = sizeof...(Views) - 1;
+    return it.it_.index() == last_idx &&
+           std::get<last_idx>(it.it_) == ranges::end(std::get<last_idx>(it.parent_->views_));
+  }
+
+  friend constexpr bool operator<(const iterator& x, const iterator& y)
+    requires(random_access_range<__maybe_const<Const, Views>> && ...)
+  {
+    return x.it_ < y.it_;
+  }
+
+  friend constexpr bool operator>(const iterator& x, const iterator& y)
+    requires(random_access_range<__maybe_const<Const, Views>> && ...)
+  {
+    return x.it_ > y.it_;
+  }
+
+  friend constexpr bool operator<=(const iterator& x, const iterator& y)
+    requires(random_access_range<__maybe_const<Const, Views>> && ...)
+  {
+    return x.it_ <= y.it_;
+  }
+
+  friend constexpr bool operator>=(const iterator& x, const iterator& y)
+    requires(random_access_range<__maybe_const<Const, Views>> && ...)
+  {
+    return x.it_ >= y.it_;
+  }
+
+  friend constexpr auto operator<=>(const iterator& x, const iterator& y)
+    requires((random_access_range<__maybe_const<Const, Views>> && ...) &&
+             (three_way_comparable<__maybe_const<Const, Views>> && ...))
+  {
+    return x.it_ <=> y.it_;
+  }
+
+  friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(
+
+      ((is_nothrow_invocable_v< decltype(ranges::iter_move), const iterator_t<__maybe_const<Const, Views>>& >) &&
+       ...) &&
+      ((is_nothrow_convertible_v< range_rvalue_reference_t<__maybe_const<Const, Views>>,
+                                  concat_rvalue_reference_t<__maybe_const<Const, Views>...> >) &&
+       ...))
+
+  {
+    return std::visit(
+        [](const auto& i) -> concat_rvalue_reference_t<__maybe_const<Const, Views>...> { return ranges::iter_move(i); },
+        it.it_);
+  }
+
+  friend constexpr void iter_swap(const iterator& x, const iterator& y)
+
+      noexcept((noexcept(ranges::swap(*x, *y))) &&
+               (noexcept(ranges::iter_swap(std::declval<const iterator_t<__maybe_const<Const, Views>>>(),
+                                           std::declval<const iterator_t<__maybe_const<Const, Views>>>())) &&
+                ...))
+
+    requires swappable_with<iter_reference_t<iterator>, iter_reference_t<iterator>> &&
+             (... && indirectly_swappable<iterator_t<__maybe_const<Const, Views>>>)
+  {
+    std::visit(
+        [&](const auto& it1, const auto& it2) {
+          if constexpr (is_same_v<decltype(it1), decltype(it2)>) {
+            ranges::iter_swap(it1, it2);
+          } else {
+            ranges::swap(*x, *y);
+          }
+        },
+        x.it_,
+        y.it_);
+  }
+
+  friend constexpr difference_type operator-(const iterator& x, const iterator& y)
+    requires concat_is_random_access<Const, Views...>
+  {
+    size_t ix = x.it_.index();
+    size_t iy = y.it_.index();
+
+    if (ix > iy) {
+      std::visit(
+          [&](auto& it_x, auto& it_y) {
+            it_x.apply_fn_with_const_index<std::tuple_size_v<decltype(x.parent_->views_)>>(
+                ix, [&](auto index_constant) {
+                  constexpr size_t index_x = index_constant.value;
+                  auto dx = ranges::__distance(ranges::begin(std::get<index_x>(x.parent_->views_)), it_x);
+
+                  it_y.apply_fn_with_const_index<std::tuple_size_v<decltype(y.parent_->views_)>>(
+                      iy, [&](auto index_constant) {
+                        constexpr size_t index_y = index_constant.value;
+                        auto dy = ranges::__distance(ranges::begin(std::get<index_y>(y.parent_->views_)), it_y);
+                        difference_type s = 0;
+                        for (size_t idx = index_y + 1; idx < index_x; idx++) {
+                          s += ranges::size(std::get<idx>(x.parent_->views_));
+                        }
+                        return dy + s + dx;
+                      });
+                });
+          },
+          x.it_,
+          y.it_);
+    } else if (ix < iy) {
+      return -(y - x);
+    } else {
+      std::visit([&](const auto& it1, const auto& it2) { return it1 - it2; }, x.it_, y.it_);
+    }
+  }
+
+  friend constexpr iterator operator-(const iterator& it, difference_type n)
+    requires concat_is_random_access<Const, Views...>
+  {
+    auto temp = it;
+    temp -= n;
+    re...
[truncated]

Copy link

github-actions bot commented Dec 22, 2024

⚠️ C/C++ code formatter, clang-format found issues in your code. ⚠️

You can test this locally with the following command:
git-clang-format --diff HEAD~1 HEAD --extensions ,h,inc,cpp -- libcxx/include/__ranges/concat_view.h libcxx/test/libcxx/ranges/range.adaptors/range.concat/iterator.valueless_by_exception.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/adaptor.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/constraints.verify.cpp libcxx/test/std/ranges/range.adaptors/range.concat/ctad.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/ctor.verify.cpp libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/end.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/compare.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/ctor.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/decrement.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/deref.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/increment.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_move.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_swap.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/member_types.compile.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/minus.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/iterator/random_access.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/size.pass.cpp libcxx/test/std/ranges/range.adaptors/range.concat/types.h libcxx/include/__ranges/concepts.h libcxx/include/ranges libcxx/include/version libcxx/modules/std/ranges.inc libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
View the diff from clang-format here.
diff --git a/libcxx/include/__ranges/concat_view.h b/libcxx/include/__ranges/concat_view.h
index 68fb2058f..be4187067 100644
--- a/libcxx/include/__ranges/concat_view.h
+++ b/libcxx/include/__ranges/concat_view.h
@@ -190,13 +190,16 @@ struct __concat_view_iterator_category<_Const, _Views...> {
 private:
   constexpr static bool __derive_pack_random_iterator =
       (derived_from<typename iterator_traits<iterator_t<__maybe_const<_Const, _Views>>>::iterator_category,
-                          random_access_iterator_tag> && ...);
+                    random_access_iterator_tag> &&
+       ...);
   constexpr static bool __derive_pack_bidirectional_iterator =
       (derived_from<typename iterator_traits<iterator_t<__maybe_const<_Const, _Views>>>::iterator_category,
-                          bidirectional_iterator_tag> && ...);
+                    bidirectional_iterator_tag> &&
+       ...);
   constexpr static bool __derive_pack_forward_iterator =
       (derived_from<typename iterator_traits< iterator_t<__maybe_const<_Const, _Views>>>::iterator_category,
-                          forward_iterator_tag> && ...);
+                    forward_iterator_tag> &&
+       ...);
 
 public:
   using iterator_category =
diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h
index edf864b53..fefec1634 100644
--- a/libcxx/include/__ranges/concepts.h
+++ b/libcxx/include/__ranges/concepts.h
@@ -172,8 +172,6 @@ concept __concatable = requires {
   typename __concat_rvalue_reference_t<_Rs...>;
 } && __concat_indirectly_readable<_Rs...>;
 
-
-
 #  endif // _LIBCPP_STD_VER >= 23
 
 } // namespace ranges
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp
index e186f3331..ce0f247dd 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/begin.pass.cpp
@@ -22,20 +22,17 @@ template <class T>
 concept HasBegin = requires(T& t) { t.begin(); };
 
 template <class T>
-concept HasConstAndNonConstBegin =
-    HasConstBegin<T> &&
-    requires(T& t, const T& ct) { requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>; };
+concept HasConstAndNonConstBegin = HasConstBegin<T> && requires(T& t, const T& ct) {
+  requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>;
+};
 
 template <class T>
-concept HasOnlyNonConstBegin = HasBegin<T> && !
-HasConstBegin<T>;
+concept HasOnlyNonConstBegin = HasBegin<T> && !HasConstBegin<T>;
 
 template <class T>
-concept HasOnlyConstBegin = HasConstBegin<T> && !
-HasConstAndNonConstBegin<T>;
+concept HasOnlyConstBegin = HasConstBegin<T> && !HasConstAndNonConstBegin<T>;
 
 constexpr void tests() {
-  
   // check the case of simple view
   {
     int buffer[4] = {1, 2, 3, 4};
@@ -82,8 +79,6 @@ constexpr void tests() {
     assert(*it == 1);
     assert(it + 4 == view.end());
   }
-
-
 }
 
 constexpr bool test() {
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp
index 75dfac667..cdaba3e91 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.default.pass.cpp
@@ -40,7 +40,7 @@ struct NoexceptView : std::ranges::view_base {
 };
 
 struct HelperView : std::ranges::view_base {
-  constexpr HelperView(const int* begin, const int *end) : begin_(begin), end_(end) {}
+  constexpr HelperView(const int* begin, const int* end) : begin_(begin), end_(end) {}
   constexpr int const* begin() const { return begin_; }
   constexpr int const* end() const { return end_; }
 
@@ -66,8 +66,8 @@ constexpr void test_with_one_view() {
 constexpr void test_with_more_than_one_view() {
   {
     using View = std::ranges::concat_view<HelperView, HelperView>;
-    int arr1[] = {1,2};
-    int arr2[] = {3,4};
+    int arr1[] = {1, 2};
+    int arr2[] = {3, 4};
     HelperView range1(arr1, arr1 + 2);
     HelperView range2(arr2, arr2 + 2);
     View view(range1, range2);
@@ -81,8 +81,7 @@ constexpr void test_with_more_than_one_view() {
   }
 }
 
-constexpr bool tests()
-{
+constexpr bool tests() {
   test_with_one_view();
   test_with_more_than_one_view();
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.verify.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.verify.cpp
index e232d240c..b540a65ed 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.verify.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.verify.cpp
@@ -19,7 +19,6 @@ struct NoSizeRange : std::ranges::view_base {
 };
 
 int main(int, char**) {
-
   {
     // LWG 4082
     std::vector<int> v{1, 2, 3};
@@ -30,7 +29,7 @@ int main(int, char**) {
 
   {
     // input is not a view
-    int x = 1;
+    int x  = 1;
     auto c = std::views::concat(x);
     // expected-error@*:* {{}}
   }
@@ -43,7 +42,7 @@ int main(int, char**) {
 
   {
     // inputs are non-concatable
-    std::vector<int> v1{1,2};
+    std::vector<int> v1{1, 2};
     std::vector<std::string> v2{"Hello", "World"};
     auto c = std::views::concat(v1, v2);
     // expected-error@*:* {{}}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp
index 53e31480a..90d290fc6 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/ctor.view.pass.cpp
@@ -25,11 +25,11 @@ private:
 };
 
 struct MoveAwareView : std::ranges::view_base {
-  int moves = 0;
+  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;
+    moves       = other.moves + 1;
     other.moves = 0;
     return *this;
   }
@@ -38,7 +38,7 @@ struct MoveAwareView : std::ranges::view_base {
 };
 
 constexpr bool test() {
-  int buff[] = {1, 2};
+  int buff[]  = {1, 2};
   int buff2[] = {3, 4};
 
   // constructor from views
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/end.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/end.pass.cpp
index 9fee816ca..eff0f99d7 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/end.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/end.pass.cpp
@@ -15,7 +15,6 @@
 #include "types.h"
 
 constexpr bool test() {
-
   int buffer1[5] = {1, 2, 3, 4, 5};
   int buffer2[2] = {6, 7};
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/compare.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/compare.pass.cpp
index b9aeb10c5..a3ae21355 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/compare.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/compare.pass.cpp
@@ -51,7 +51,8 @@ constexpr void test() {
     std::same_as<bool> decltype(auto) result = (it1 == it2);
     assert(result);
 
-    ++it2; ++it2;
+    ++it2;
+    ++it2;
     assert(!(it1 == it2));
     ++it2;
     assert(*it1 == *it2);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/deref.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/deref.pass.cpp
index 4dd71170e..6af8d415f 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/deref.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/deref.pass.cpp
@@ -17,7 +17,6 @@
 
 template <class Iter, class ValueType = int, class Sent = sentinel_wrapper<Iter>>
 constexpr void test() {
-
   {
     // test with one view
     using View           = minimal_view<Iter, Sent>;
@@ -42,8 +41,8 @@ constexpr void test() {
     std::array<int, 3> array1{0, 1, 2};
     std::array<int, 3> array2{0, 1, 2};
     std::ranges::concat_view view(std::views::all(array1), std::views::all(array2));
-    decltype(auto) it1                       = view.begin();
-    decltype(auto) it2                       = view.begin() + 3;
+    decltype(auto) it1 = view.begin();
+    decltype(auto) it2 = view.begin() + 3;
 
     ASSERT_SAME_TYPE(int&, decltype(*it1));
     assert(*it1 == *it2);
@@ -54,8 +53,8 @@ constexpr void test() {
     constexpr static std::array<int, 3> array1{0, 1, 2};
     constexpr static std::array<int, 3> array2{0, 1, 2};
     constexpr static std::ranges::concat_view view(std::views::all(array1), std::views::all(array2));
-    decltype(auto) it1                       = view.begin();
-    decltype(auto) it2                       = view.begin() + 3;
+    decltype(auto) it1 = view.begin();
+    decltype(auto) it2 = view.begin() + 3;
 
     ASSERT_SAME_TYPE(const int&, decltype(*it1));
     assert(*it1 == *it2);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_move.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_move.pass.cpp
index fbaae4d25..203b42856 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_move.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_move.pass.cpp
@@ -36,8 +36,8 @@ struct ThrowingMove {
 
 template <class Iterator, bool HasNoexceptIterMove>
 constexpr bool test() {
-  using Sentinel       = sentinel_wrapper<Iterator>;
-  using View           = minimal_view<Iterator, Sentinel>;
+  using Sentinel = sentinel_wrapper<Iterator>;
+  using View     = minimal_view<Iterator, Sentinel>;
 
   {
     std::array<int, 5> array1{0, 1, 2, 3, 4};
@@ -61,7 +61,6 @@ constexpr bool test() {
     static_assert(!noexcept(std::ranges::iter_move(it)));
   }
 
-
   return true;
 }
 
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_swap.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_swap.pass.cpp
index fab63f978..6cacbc15b 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_swap.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/iter_swap.pass.cpp
@@ -24,7 +24,7 @@ concept has_iter_swap = requires(It it) { std::ranges::iter_swap(it, it); };
 struct ThrowingMove {
   ThrowingMove() = default;
   ThrowingMove(ThrowingMove&&) {}
-  ThrowingMove& operator=(ThrowingMove&&){return *this;}
+  ThrowingMove& operator=(ThrowingMove&&) { return *this; }
 };
 
 template <class Iterator, bool IsNoexcept>
@@ -41,8 +41,8 @@ constexpr void test() {
     View v2{Iterator(array2.data()), Sentinel(Iterator(array2.data() + array2.size()))};
     std::ranges::concat_view view(std::move(v1), std::move(v2));
 
-    auto it1                = view.begin();
-    auto it2                = ++view.begin();
+    auto it1 = view.begin();
+    auto it2 = ++view.begin();
 
     static_assert(std::is_same_v<decltype(iter_swap(it1, it2)), void>);
     static_assert(noexcept(iter_swap(it1, it2)) == IsNoexcept);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/member_types.compile.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/member_types.compile.pass.cpp
index 6e4fc40d9..1849f6abd 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/member_types.compile.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/member_types.compile.pass.cpp
@@ -34,8 +34,8 @@ concept HasIterCategory = requires { typename T::iterator_category; };
 template <class T>
 struct DiffTypeIter {
   using iterator_category = std::input_iterator_tag;
-  using value_type = int;
-  using difference_type = T;
+  using value_type        = int;
+  using difference_type   = T;
 
   int operator*() const;
   DiffTypeIter& operator++();
@@ -74,7 +74,6 @@ void test() {
     static_assert(HasIterCategory<Iter>);
   }
 
-
   {
     // 3 views
     std::ranges::concat_view v(buffer, buffer, buffer);
@@ -87,7 +86,6 @@ void test() {
     static_assert(HasIterCategory<Iter>);
   }
 
-
   {
     // bidirectional_iterator_tag
     std::ranges::concat_view v(BidiCommonView{buffer});
@@ -99,8 +97,6 @@ void test() {
     static_assert(std::is_same_v<Iter::value_type, int>);
   }
 
-
-
   {
     // forward_iterator_tag
     using Iter = std::ranges::iterator_t<std::ranges::concat_view<ForwardView<int>>>;
@@ -147,7 +143,7 @@ void test() {
   {
     // const-iterator different from iterator
     std::ranges::concat_view v{ConstVeryDifferentRange{}};
-    using Iter = decltype(v.begin());
+    using Iter      = decltype(v.begin());
     using ConstIter = decltype(std::as_const(v).begin());
 
     static_assert(std::is_same_v<Iter::iterator_concept, std::random_access_iterator_tag>);
@@ -160,5 +156,4 @@ void test() {
     static_assert(std::is_same_v<ConstIter::difference_type, std::ptrdiff_t>);
     static_assert(std::is_same_v<ConstIter::value_type, double>);
   }
-
 }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/random_access.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/random_access.pass.cpp
index 0711e99dc..69afe2c4d 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/random_access.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/iterator/random_access.pass.cpp
@@ -45,7 +45,7 @@ constexpr bool test() {
   {
     // random_access_range and non common range
     std::ranges::concat_view v(SimpleNonCommonRandomAccessSized{buffer1}, NonSimpleCommonRandomAccessSized{buffer2});
-    auto it = v.begin();
+    auto it                 = v.begin();
     const auto canSubscript = [](auto&& it) { return requires { it[0]; }; };
     static_assert(!canSubscript(it));
 
@@ -66,7 +66,7 @@ constexpr bool test() {
   {
     // non random_access_range
     std::ranges::concat_view v(BidiCommonView{buffer1});
-    auto iter = v.begin();
+    auto iter               = v.begin();
     const auto canSubscript = [](auto&& it) { return requires { it[0]; }; };
     static_assert(!canSubscript(iter));
   }
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/size.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.concat/size.pass.cpp
index 9a4d331dd..8503cff87 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/size.pass.cpp
@@ -23,7 +23,7 @@ struct View : std::ranges::view_base {
 };
 
 struct SizedNonConst : std::ranges::view_base {
-  using iterator = forward_iterator<int*>;
+  using iterator    = forward_iterator<int*>;
   std::size_t size_ = 0;
   constexpr SizedNonConst(std::size_t s) : size_(s) {}
   constexpr auto begin() const { return iterator{buffer}; }
@@ -45,8 +45,7 @@ struct NoSizeView : std::ranges::view_base {
 };
 
 constexpr bool test() {
-
-   {
+  {
     // single range
     std::ranges::concat_view v(View(8));
     assert(v.size() == 8);
diff --git a/libcxx/test/std/ranges/range.adaptors/range.concat/types.h b/libcxx/test/std/ranges/range.adaptors/range.concat/types.h
index 23a03aaab..4a25b4d07 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.concat/types.h
+++ b/libcxx/test/std/ranges/range.adaptors/range.concat/types.h
@@ -54,7 +54,7 @@ struct BufferView : std::ranges::view_base {
 using IntBufferView = BufferView<int>;
 
 template <bool Simple>
-struct Common :  IntBufferView {
+struct Common : IntBufferView {
   using IntBufferView::IntBufferView;
 
   constexpr int* begin()
@@ -71,49 +71,53 @@ struct Common :  IntBufferView {
   constexpr const int* end() const { return buffer_ + size_; }
 };
 
-using SimpleCommon = Common<true>;
+using SimpleCommon    = Common<true>;
 using NonSimpleCommon = Common<false>;
 
-using SimpleCommonRandomAccessSized = SimpleCommon;
+using SimpleCommonRandomAccessSized    = SimpleCommon;
 using NonSimpleCommonRandomAccessSized = NonSimpleCommon;
 
 template <bool Simple>
 struct NonCommon : IntBufferView {
   using IntBufferView::IntBufferView;
   constexpr int* begin()
-    requires(!Simple) {
+    requires(!Simple)
+  {
     return buffer_;
   }
   constexpr const int* begin() const { return buffer_; }
   constexpr sentinel_wrapper<int*> end()
-    requires(!Simple) {
+    requires(!Simple)
+  {
     return sentinel_wrapper<int*>(buffer_ + size_);
   }
   constexpr sentinel_wrapper<const int*> end() const { return sentinel_wrapper<const int*>(buffer_ + size_); }
 };
 
-using SimpleNonCommon = NonCommon<true>;
+using SimpleNonCommon    = NonCommon<true>;
 using NonSimpleNonCommon = NonCommon<false>;
 
 template <bool Simple>
 struct NonCommonSized : IntBufferView {
   using IntBufferView::IntBufferView;
   constexpr int* begin()
-    requires(!Simple) {
+    requires(!Simple)
+  {
     return buffer_;
   }
   constexpr const int* begin() const { return buffer_; }
   constexpr sentinel_wrapper<int*> end()
-    requires(!Simple) {
+    requires(!Simple)
+  {
     return sentinel_wrapper<int*>(buffer_ + size_);
   }
   constexpr sentinel_wrapper<const int*> end() const { return sentinel_wrapper<const int*>(buffer_ + size_); }
   constexpr std::size_t size() const { return size_; }
 };
 
-using SimpleNonCommonSized = NonCommonSized<true>;
+using SimpleNonCommonSized                = NonCommonSized<true>;
 using SimpleNonCommonRandomAccessSized    = SimpleNonCommonSized;
-using NonSimpleNonCommonSized = NonCommonSized<false>;
+using NonSimpleNonCommonSized             = NonCommonSized<false>;
 using NonSimpleNonCommonRandomAccessSized = NonSimpleNonCommonSized;
 
 template <bool Simple>
@@ -121,15 +125,17 @@ struct NonCommonNonRandom : IntBufferView {
   using IntBufferView::IntBufferView;
 
   using const_iterator = forward_iterator<const int*>;
-  using iterator = forward_iterator<int*>;
+  using iterator       = forward_iterator<int*>;
 
   constexpr iterator begin()
-    requires(!Simple) {
+    requires(!Simple)
+  {
     return iterator(buffer_);
   }
   constexpr const_iterator begin() const { return const_iterator(buffer_); }
   constexpr sentinel_wrapper<iterator> end()
-    requires(!Simple) {
+    requires(!Simple)
+  {
     return sentinel_wrapper<iterator>(iterator(buffer_ + size_));
   }
   constexpr sentinel_wrapper<const_iterator> end() const {
@@ -137,7 +143,7 @@ struct NonCommonNonRandom : IntBufferView {
   }
 };
 
-using SimpleNonCommonNonRandom = NonCommonNonRandom<true>;
+using SimpleNonCommonNonRandom    = NonCommonNonRandom<true>;
 using NonSimpleNonCommonNonRandom = NonCommonNonRandom<false>;
 
 template <class Iter, class Sent = Iter, class NonConstIter = Iter, class NonConstSent = Sent>
@@ -145,13 +151,15 @@ struct BasicView : IntBufferView {
   using IntBufferView::IntBufferView;
 
   constexpr NonConstIter begin()
-    requires(!std::is_same_v<Iter, NonConstIter>) {
+    requires(!std::is_same_v<Iter, NonConstIter>)
+  {
     return NonConstIter(buffer_);
   }
   constexpr Iter begin() const { return Iter(buffer_); }
 
   constexpr NonConstSent end()
-    requires(!std::is_same_v<Sent, NonConstSent>) {
+    requires(!std::is_same_v<Sent, NonConstSent>)
+  {
     if constexpr (std::is_same_v<NonConstIter, NonConstSent>) {
       return NonConstIter(buffer_ + size_);
     } else {
@@ -173,5 +181,4 @@ using NonSizedRandomAccessView =
 
 using InputCommonView = BasicView<common_input_iterator<int*>>;
 
-
 #endif // TEST_STD_RANGES_RANGE_ADAPTORS_CONCAT_FILTER_TYPES_H

@changkhothuychung changkhothuychung marked this pull request as ready for review December 23, 2024 05:45
@changkhothuychung
Copy link
Contributor Author

I have no idea why I am getting error: no type named 'concat_view' in namespace 'std::ranges' in the buildkite. My test runs successfully locally. Does anyone know what is wrong?

@changkhothuychung changkhothuychung changed the title [libcxx] implement views::concat [libc++] implement views::concat Dec 23, 2024
Copy link
Contributor

@philnik777 philnik777 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make sure you're following the libc++ Coding Guidelines.

@changkhothuychung
Copy link
Contributor Author

Hi @huixie90 , I addressed most of the comments, and need your follow-ups on the remaining ones. Thanks!

@huixie90
Copy link
Member

will have a pass today

Copy link
Member

@huixie90 huixie90 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I only looked the concat_view and the tests for concat_view itself. i have not look at the iterators yet. I think we need a bit more test coverage, especially we need to tests that concat more than one ranges. Could you please also go over the iterator tests with respect to the spec. Ideally, every single word in the spec needs to be tested. Thanks a lot for your contribution

#include <__ranges/range_adaptor.h>
#include <__ranges/size.h>
#include <__ranges/view_interface.h>
#include <__ranges/zip_view.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the reason to include this header?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to use ranges::__tuple_transform in the size() function, which is defined in zip_view.h

Should we move that function to a sharable place?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ideally yes as concat isn't directly related to zip. That being said, I don't know the best place to put it. perhaps consider a separate header inside the __ranges folder?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have a suggestion what should be the name of that file under __ranges folder?

@changkhothuychung changkhothuychung marked this pull request as draft August 5, 2025 20:07
@changkhothuychung
Copy link
Contributor Author

@huixie90 also by looking at the file names of iterator test, do you expect any other test?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++26 libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
9 participants