aboutsummaryrefslogtreecommitdiff
path: root/libcxx/include/__ranges
diff options
context:
space:
mode:
Diffstat (limited to 'libcxx/include/__ranges')
-rw-r--r--libcxx/include/__ranges/access.h222
-rw-r--r--libcxx/include/__ranges/all.h86
-rw-r--r--libcxx/include/__ranges/common_view.h113
-rw-r--r--libcxx/include/__ranges/concepts.h138
-rw-r--r--libcxx/include/__ranges/copyable_box.h175
-rw-r--r--libcxx/include/__ranges/dangling.h47
-rw-r--r--libcxx/include/__ranges/data.h86
-rw-r--r--libcxx/include/__ranges/drop_view.h131
-rw-r--r--libcxx/include/__ranges/empty.h86
-rw-r--r--libcxx/include/__ranges/empty_view.h46
-rw-r--r--libcxx/include/__ranges/enable_borrowed_range.h46
-rw-r--r--libcxx/include/__ranges/enable_view.h42
-rw-r--r--libcxx/include/__ranges/non_propagating_cache.h99
-rw-r--r--libcxx/include/__ranges/ref_view.h87
-rw-r--r--libcxx/include/__ranges/size.h132
-rw-r--r--libcxx/include/__ranges/subrange.h267
-rw-r--r--libcxx/include/__ranges/transform_view.h408
-rw-r--r--libcxx/include/__ranges/view_interface.h198
18 files changed, 2409 insertions, 0 deletions
diff --git a/libcxx/include/__ranges/access.h b/libcxx/include/__ranges/access.h
new file mode 100644
index 000000000000..add848887c11
--- /dev/null
+++ b/libcxx/include/__ranges/access.h
@@ -0,0 +1,222 @@
+// -*- C++ -*-
+//===------------------------ __ranges/access.h ---------------------------===//
+//
+// 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_ACCESS_H
+#define _LIBCPP___RANGES_ACCESS_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/readable_traits.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__utility/__decay_copy.h>
+#include <__utility/forward.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+// clang-format off
+
+namespace ranges {
+ template <class _Tp>
+ concept __can_borrow =
+ is_lvalue_reference_v<_Tp> || enable_borrowed_range<remove_cvref_t<_Tp> >;
+
+ template<class _Tp>
+ concept __is_complete = requires { sizeof(_Tp); };
+} // namespace ranges
+
+// [range.access.begin]
+namespace ranges::__begin {
+ template <class _Tp>
+ concept __member_begin =
+ __can_borrow<_Tp> &&
+ requires(_Tp&& __t) {
+ { _VSTD::__decay_copy(__t.begin()) } -> input_or_output_iterator;
+ };
+
+ void begin(auto&) = delete;
+ void begin(const auto&) = delete;
+
+ template <class _Tp>
+ concept __unqualified_begin =
+ !__member_begin<_Tp> &&
+ __can_borrow<_Tp> &&
+ __class_or_enum<remove_cvref_t<_Tp> > &&
+ requires(_Tp && __t) {
+ { _VSTD::__decay_copy(begin(__t)) } -> input_or_output_iterator;
+ };
+
+ struct __fn {
+ template <class _Tp>
+ requires is_array_v<remove_cv_t<_Tp>>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const noexcept {
+ constexpr bool __complete = __is_complete<iter_value_t<_Tp> >;
+ if constexpr (__complete) { // used to disable cryptic diagnostic
+ return __t + 0;
+ }
+ else {
+ static_assert(__complete, "`std::ranges::begin` is SFINAE-unfriendly on arrays of an incomplete type.");
+ }
+ }
+
+ template <class _Tp>
+ requires __member_begin<_Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::__decay_copy(__t.begin())))
+ {
+ return __t.begin();
+ }
+
+ template <class _Tp>
+ requires __unqualified_begin<_Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::__decay_copy(begin(__t))))
+ {
+ return begin(__t);
+ }
+
+ void operator()(auto&&) const = delete;
+ };
+} // namespace ranges::__begin
+
+namespace ranges {
+ inline namespace __cpo {
+ inline constexpr auto begin = __begin::__fn{};
+ } // namespace __cpo
+
+ template <class _Tp>
+ using iterator_t = decltype(ranges::begin(declval<_Tp&>()));
+} // namespace ranges
+
+// [range.access.end]
+namespace ranges::__end {
+ template <class _Tp>
+ concept __member_end =
+ __can_borrow<_Tp> &&
+ requires(_Tp&& __t) {
+ typename iterator_t<_Tp>;
+ { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).end()) } -> sentinel_for<iterator_t<_Tp> >;
+ };
+
+ void end(auto&) = delete;
+ void end(const auto&) = delete;
+
+ template <class _Tp>
+ concept __unqualified_end =
+ !__member_end<_Tp> &&
+ __can_borrow<_Tp> &&
+ __class_or_enum<remove_cvref_t<_Tp> > &&
+ requires(_Tp && __t) {
+ typename iterator_t<_Tp>;
+ { _VSTD::__decay_copy(end(_VSTD::forward<_Tp>(__t))) } -> sentinel_for<iterator_t<_Tp> >;
+ };
+
+ class __fn {
+ public:
+ template <class _Tp, size_t _Np>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp (&__t)[_Np]) const noexcept {
+ constexpr bool __complete = __is_complete<remove_cv_t<_Tp> >;
+ if constexpr (__complete) { // used to disable cryptic diagnostic
+ return __t + _Np;
+ }
+ else {
+ static_assert(__complete, "`std::ranges::end` is SFINAE-unfriendly on arrays of an incomplete type.");
+ }
+ }
+
+ template <class _Tp>
+ requires __member_end<_Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::__decay_copy(__t.end())))
+ {
+ return _VSTD::forward<_Tp>(__t).end();
+ }
+
+ template <class _Tp>
+ requires __unqualified_end<_Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::__decay_copy(end(__t))))
+ {
+ return end(__t);
+ }
+
+ void operator()(auto&&) const = delete;
+ };
+} // namespace ranges::__end
+
+namespace ranges::inline __cpo {
+ inline constexpr auto end = __end::__fn{};
+} // namespace ranges::__cpo
+
+namespace ranges::__cbegin {
+ struct __fn {
+ template <class _Tp>
+ requires invocable<decltype(ranges::begin), _Tp const&>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const
+ noexcept(noexcept(ranges::begin(_VSTD::as_const(__t))))
+ {
+ return ranges::begin(_VSTD::as_const(__t));
+ }
+
+ template <class _Tp>
+ requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::begin), _Tp const&&>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::begin(static_cast<_Tp const&&>(__t))))
+ {
+ return ranges::begin(static_cast<_Tp const&&>(__t));
+ }
+ };
+} // namespace ranges::__cbegin
+
+namespace ranges::inline __cpo {
+ inline constexpr auto cbegin = __cbegin::__fn{};
+} // namespace ranges::__cpo
+
+namespace ranges::__cend {
+ struct __fn {
+ template <class _Tp>
+ requires invocable<decltype(ranges::end), _Tp const&>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __t) const
+ noexcept(noexcept(ranges::end(_VSTD::as_const(__t))))
+ {
+ return ranges::end(_VSTD::as_const(__t));
+ }
+
+ template <class _Tp>
+ requires is_rvalue_reference_v<_Tp> && invocable<decltype(ranges::end), _Tp const&&>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::end(static_cast<_Tp const&&>(__t))))
+ {
+ return ranges::end(static_cast<_Tp const&&>(__t));
+ }
+ };
+} // namespace ranges::__cend
+
+namespace ranges::inline __cpo {
+ inline constexpr auto cend = __cend::__fn{};
+} // namespace ranges::__cpo
+
+// clang-format off
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_ACCESS_H
diff --git a/libcxx/include/__ranges/all.h b/libcxx/include/__ranges/all.h
new file mode 100644
index 000000000000..d678d3e5d357
--- /dev/null
+++ b/libcxx/include/__ranges/all.h
@@ -0,0 +1,86 @@
+// -*- 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_ALL_H
+#define _LIBCPP___RANGES_ALL_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/ref_view.h>
+#include <__ranges/subrange.h>
+#include <__utility/__decay_copy.h>
+#include <__utility/declval.h>
+#include <__utility/forward.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace views {
+
+namespace __all {
+ struct __fn {
+ template<class _Tp>
+ requires ranges::view<decay_t<_Tp>>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::__decay_copy(_VSTD::forward<_Tp>(__t))))
+ {
+ return _VSTD::forward<_Tp>(__t);
+ }
+
+ template<class _Tp>
+ requires (!ranges::view<decay_t<_Tp>>) &&
+ requires (_Tp&& __t) { ranges::ref_view{_VSTD::forward<_Tp>(__t)}; }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::ref_view{_VSTD::forward<_Tp>(__t)}))
+ {
+ return ranges::ref_view{_VSTD::forward<_Tp>(__t)};
+ }
+
+ template<class _Tp>
+ requires (!ranges::view<decay_t<_Tp>> &&
+ !requires (_Tp&& __t) { ranges::ref_view{_VSTD::forward<_Tp>(__t)}; } &&
+ requires (_Tp&& __t) { ranges::subrange{_VSTD::forward<_Tp>(__t)}; })
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::subrange{_VSTD::forward<_Tp>(__t)}))
+ {
+ return ranges::subrange{_VSTD::forward<_Tp>(__t)};
+ }
+ };
+}
+
+inline namespace __cpo {
+ inline constexpr auto all = __all::__fn{};
+} // namespace __cpo
+
+template<ranges::viewable_range _Range>
+using all_t = decltype(views::all(declval<_Range>()));
+
+} // namespace views
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_ALL_H
diff --git a/libcxx/include/__ranges/common_view.h b/libcxx/include/__ranges/common_view.h
new file mode 100644
index 000000000000..dab82602f671
--- /dev/null
+++ b/libcxx/include/__ranges/common_view.h
@@ -0,0 +1,113 @@
+// -*- 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_COMMON_VIEW_H
+#define _LIBCPP___RANGES_COMMON_VIEW_H
+
+#include <__config>
+#include <__iterator/common_iterator.h>
+#include <__iterator/iterator_traits.h>
+#include <__ranges/access.h>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/size.h>
+#include <__ranges/view_interface.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+
+template<view _View>
+ requires (!common_range<_View> && copyable<iterator_t<_View>>)
+class common_view : public view_interface<common_view<_View>> {
+ _View __base_ = _View();
+
+public:
+ _LIBCPP_HIDE_FROM_ABI
+ common_view() requires default_initializable<_View> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit common_view(_View __v) : __base_(_VSTD::move(__v)) { }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _View base() && { return _VSTD::move(__base_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto begin() {
+ if constexpr (random_access_range<_View> && sized_range<_View>)
+ return ranges::begin(__base_);
+ else
+ return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::begin(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto begin() const requires range<const _View> {
+ if constexpr (random_access_range<const _View> && sized_range<const _View>)
+ return ranges::begin(__base_);
+ else
+ return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto end() {
+ if constexpr (random_access_range<_View> && sized_range<_View>)
+ return ranges::begin(__base_) + ranges::size(__base_);
+ else
+ return common_iterator<iterator_t<_View>, sentinel_t<_View>>(ranges::end(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto end() const requires range<const _View> {
+ if constexpr (random_access_range<const _View> && sized_range<const _View>)
+ return ranges::begin(__base_) + ranges::size(__base_);
+ else
+ return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::end(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() requires sized_range<_View> {
+ return ranges::size(__base_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() const requires sized_range<const _View> {
+ return ranges::size(__base_);
+ }
+};
+
+template<class _Range>
+common_view(_Range&&)
+ -> common_view<views::all_t<_Range>>;
+
+template<class _View>
+inline constexpr bool enable_borrowed_range<common_view<_View>> = enable_borrowed_range<_View>;
+
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_COMMON_VIEW_H
diff --git a/libcxx/include/__ranges/concepts.h b/libcxx/include/__ranges/concepts.h
new file mode 100644
index 000000000000..2f912c2841e8
--- /dev/null
+++ b/libcxx/include/__ranges/concepts.h
@@ -0,0 +1,138 @@
+// -*- C++ -*-
+//===--------------------- __ranges/concepts.h ----------------------------===//
+//
+// 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_CONCEPTS_H
+#define _LIBCPP___RANGES_CONCEPTS_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iter_move.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/readable_traits.h>
+#include <__ranges/access.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/data.h>
+#include <__ranges/enable_view.h>
+#include <__ranges/size.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// clang-format off
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+ // [range.range]
+ template <class _Tp>
+ concept range = requires(_Tp& __t) {
+ ranges::begin(__t); // sometimes equality-preserving
+ ranges::end(__t);
+ };
+
+ template<class _Range>
+ concept borrowed_range = range<_Range> &&
+ (is_lvalue_reference_v<_Range> || enable_borrowed_range<remove_cvref_t<_Range>>);
+
+ // `iterator_t` defined in <__ranges/access.h>
+
+ template <range _Rp>
+ using sentinel_t = decltype(ranges::end(declval<_Rp&>()));
+
+ template <range _Rp>
+ using range_difference_t = iter_difference_t<iterator_t<_Rp>>;
+
+ template <range _Rp>
+ using range_value_t = iter_value_t<iterator_t<_Rp>>;
+
+ template <range _Rp>
+ using range_reference_t = iter_reference_t<iterator_t<_Rp>>;
+
+ template <range _Rp>
+ using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<_Rp>>;
+
+ // [range.sized]
+ template <class _Tp>
+ concept sized_range = range<_Tp> && requires(_Tp& __t) { ranges::size(__t); };
+
+ template<sized_range _Rp>
+ using range_size_t = decltype(ranges::size(declval<_Rp&>()));
+
+ // `disable_sized_range` defined in `<__ranges/size.h>`
+
+ // [range.view], views
+
+ // `enable_view` defined in <__ranges/enable_view.h>
+ // `view_base` defined in <__ranges/enable_view.h>
+
+ template <class _Tp>
+ concept view =
+ range<_Tp> &&
+ movable<_Tp> &&
+ enable_view<_Tp>;
+
+ template<class _Range>
+ concept __simple_view =
+ view<_Range> && range<const _Range> &&
+ same_as<iterator_t<_Range>, iterator_t<const _Range>> &&
+ same_as<sentinel_t<_Range>, iterator_t<const _Range>>;
+
+ // [range.refinements], other range refinements
+ template <class _Rp, class _Tp>
+ concept output_range = range<_Rp> && output_iterator<iterator_t<_Rp>, _Tp>;
+
+ template <class _Tp>
+ concept input_range = range<_Tp> && input_iterator<iterator_t<_Tp>>;
+
+ template <class _Tp>
+ concept forward_range = input_range<_Tp> && forward_iterator<iterator_t<_Tp>>;
+
+ template <class _Tp>
+ concept bidirectional_range = forward_range<_Tp> && bidirectional_iterator<iterator_t<_Tp>>;
+
+ template <class _Tp>
+ concept random_access_range =
+ bidirectional_range<_Tp> && random_access_iterator<iterator_t<_Tp>>;
+
+ template<class _Tp>
+ concept contiguous_range =
+ random_access_range<_Tp> &&
+ contiguous_iterator<iterator_t<_Tp>> &&
+ requires(_Tp& __t) {
+ { ranges::data(__t) } -> same_as<add_pointer_t<range_reference_t<_Tp>>>;
+ };
+
+ template <class _Tp>
+ concept common_range = range<_Tp> && same_as<iterator_t<_Tp>, sentinel_t<_Tp>>;
+
+ template<class _Tp>
+ concept viewable_range =
+ range<_Tp> && (
+ (view<remove_cvref_t<_Tp>> && constructible_from<remove_cvref_t<_Tp>, _Tp>) ||
+ (!view<remove_cvref_t<_Tp>> && borrowed_range<_Tp>)
+ );
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+// clang-format on
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_CONCEPTS_H
diff --git a/libcxx/include/__ranges/copyable_box.h b/libcxx/include/__ranges/copyable_box.h
new file mode 100644
index 000000000000..f2d3843f79f5
--- /dev/null
+++ b/libcxx/include/__ranges/copyable_box.h
@@ -0,0 +1,175 @@
+// -*- 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_COPYABLE_BOX_H
+#define _LIBCPP___RANGES_COPYABLE_BOX_H
+
+#include <__config>
+#include <__memory/addressof.h>
+#include <__memory/construct_at.h>
+#include <__utility/move.h>
+#include <concepts>
+#include <optional>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+// __copyable_box allows turning a type that is copy-constructible (but maybe not copy-assignable) into
+// a type that is both copy-constructible and copy-assignable. It does that by introducing an empty state
+// and basically doing destroy-then-copy-construct in the assignment operator. The empty state is necessary
+// to handle the case where the copy construction fails after destroying the object.
+//
+// In some cases, we can completely avoid the use of an empty state; we provide a specialization of
+// __copyable_box that does this, see below for the details.
+
+template<class _Tp>
+concept __copy_constructible_object = copy_constructible<_Tp> && is_object_v<_Tp>;
+
+namespace ranges {
+ // Primary template - uses std::optional and introduces an empty state in case assignment fails.
+ template<__copy_constructible_object _Tp>
+ class __copyable_box {
+ [[no_unique_address]] optional<_Tp> __val_;
+
+ public:
+ template<class ..._Args>
+ requires is_constructible_v<_Tp, _Args...>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit __copyable_box(in_place_t, _Args&& ...__args)
+ noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
+ : __val_(in_place, _VSTD::forward<_Args>(__args)...)
+ { }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>)
+ requires default_initializable<_Tp>
+ : __val_(in_place)
+ { }
+
+ _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default;
+ _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __copyable_box& operator=(__copyable_box const& __other)
+ noexcept(is_nothrow_copy_constructible_v<_Tp>)
+ {
+ if (this != _VSTD::addressof(__other)) {
+ if (__other.__has_value()) __val_.emplace(*__other);
+ else __val_.reset();
+ }
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __copyable_box& operator=(__copyable_box&& __other)
+ noexcept(is_nothrow_move_constructible_v<_Tp>)
+ {
+ if (this != _VSTD::addressof(__other)) {
+ if (__other.__has_value()) __val_.emplace(_VSTD::move(*__other));
+ else __val_.reset();
+ }
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return *__val_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return *__val_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return __val_.has_value(); }
+ };
+
+ // This partial specialization implements an optimization for when we know we don't need to store
+ // an empty state to represent failure to perform an assignment. For copy-assignment, this happens:
+ //
+ // 1. If the type is copyable (which includes copy-assignment), we can use the type's own assignment operator
+ // directly and avoid using std::optional.
+ // 2. If the type is not copyable, but it is nothrow-copy-constructible, then we can implement assignment as
+ // destroy-and-then-construct and we know it will never fail, so we don't need an empty state.
+ //
+ // The exact same reasoning can be applied for move-assignment, with copyable replaced by movable and
+ // nothrow-copy-constructible replaced by nothrow-move-constructible. This specialization is enabled
+ // whenever we can apply any of these optimizations for both the copy assignment and the move assignment
+ // operator.
+ template<class _Tp>
+ concept __doesnt_need_empty_state_for_copy = copyable<_Tp> || is_nothrow_copy_constructible_v<_Tp>;
+
+ template<class _Tp>
+ concept __doesnt_need_empty_state_for_move = movable<_Tp> || is_nothrow_move_constructible_v<_Tp>;
+
+ template<__copy_constructible_object _Tp>
+ requires __doesnt_need_empty_state_for_copy<_Tp> && __doesnt_need_empty_state_for_move<_Tp>
+ class __copyable_box<_Tp> {
+ [[no_unique_address]] _Tp __val_;
+
+ public:
+ template<class ..._Args>
+ requires is_constructible_v<_Tp, _Args...>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit __copyable_box(in_place_t, _Args&& ...__args)
+ noexcept(is_nothrow_constructible_v<_Tp, _Args...>)
+ : __val_(_VSTD::forward<_Args>(__args)...)
+ { }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __copyable_box() noexcept(is_nothrow_default_constructible_v<_Tp>)
+ requires default_initializable<_Tp>
+ : __val_()
+ { }
+
+ _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box const&) = default;
+ _LIBCPP_HIDE_FROM_ABI __copyable_box(__copyable_box&&) = default;
+
+ // Implementation of assignment operators in case we perform optimization (1)
+ _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box const&) requires copyable<_Tp> = default;
+ _LIBCPP_HIDE_FROM_ABI __copyable_box& operator=(__copyable_box&&) requires movable<_Tp> = default;
+
+ // Implementation of assignment operators in case we perform optimization (2)
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __copyable_box& operator=(__copyable_box const& __other) noexcept {
+ static_assert(is_nothrow_copy_constructible_v<_Tp>);
+ if (this != _VSTD::addressof(__other)) {
+ _VSTD::destroy_at(_VSTD::addressof(__val_));
+ _VSTD::construct_at(_VSTD::addressof(__val_), __other.__val_);
+ }
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __copyable_box& operator=(__copyable_box&& __other) noexcept {
+ static_assert(is_nothrow_move_constructible_v<_Tp>);
+ if (this != _VSTD::addressof(__other)) {
+ _VSTD::destroy_at(_VSTD::addressof(__val_));
+ _VSTD::construct_at(_VSTD::addressof(__val_), _VSTD::move(__other.__val_));
+ }
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp const& operator*() const noexcept { return __val_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr _Tp& operator*() noexcept { return __val_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr bool __has_value() const noexcept { return true; }
+ };
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_COPYABLE_BOX_H
diff --git a/libcxx/include/__ranges/dangling.h b/libcxx/include/__ranges/dangling.h
new file mode 100644
index 000000000000..deb02a1a448d
--- /dev/null
+++ b/libcxx/include/__ranges/dangling.h
@@ -0,0 +1,47 @@
+// -*- 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_DANGLING_H
+#define _LIBCPP___RANGES_DANGLING_H
+
+#include <__config>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+struct dangling {
+ dangling() = default;
+ _LIBCPP_HIDE_FROM_ABI constexpr dangling(auto&&...) noexcept {}
+};
+
+template <range _Rp>
+using borrowed_iterator_t = _If<borrowed_range<_Rp>, iterator_t<_Rp>, dangling>;
+
+// borrowed_subrange_t defined in <__ranges/subrange.h>
+} // namespace ranges
+
+#endif // !_LIBCPP_HAS_NO_RANGES
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_DANGLING_H
diff --git a/libcxx/include/__ranges/data.h b/libcxx/include/__ranges/data.h
new file mode 100644
index 000000000000..dae30984d3f9
--- /dev/null
+++ b/libcxx/include/__ranges/data.h
@@ -0,0 +1,86 @@
+// -*- C++ -*-
+//===------------------------ __ranges/data.h ------------------------------===//
+//
+// 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_DATA_H
+#define _LIBCPP___RANGES_DATA_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/pointer_traits.h>
+#include <__ranges/access.h>
+#include <__utility/forward.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+// clang-format off
+namespace ranges {
+// [range.prim.data]
+namespace __data {
+ template <class _Tp>
+ concept __ptr_to_object = is_pointer_v<_Tp> && is_object_v<remove_pointer_t<_Tp>>;
+
+ template <class _Tp>
+ concept __member_data =
+ requires(_Tp&& __t) {
+ { _VSTD::forward<_Tp>(__t) } -> __can_borrow;
+ { __t.data() } -> __ptr_to_object;
+ };
+
+ template <class _Tp>
+ concept __ranges_begin_invocable =
+ !__member_data<_Tp> &&
+ requires(_Tp&& __t) {
+ { _VSTD::forward<_Tp>(__t) } -> __can_borrow;
+ { ranges::begin(_VSTD::forward<_Tp>(__t)) } -> contiguous_iterator;
+ };
+
+ struct __fn {
+ template <__member_data _Tp>
+ requires __can_borrow<_Tp>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __ptr_to_object auto operator()(_Tp&& __t) const
+ noexcept(noexcept(__t.data())) {
+ return __t.data();
+ }
+
+ template<__ranges_begin_invocable _Tp>
+ requires __can_borrow<_Tp>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __ptr_to_object auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t))))) {
+ return _VSTD::to_address(ranges::begin(_VSTD::forward<_Tp>(__t)));
+ }
+ };
+} // end namespace __data
+
+inline namespace __cpo {
+ inline constexpr const auto data = __data::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+// clang-format off
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_DATA_H
diff --git a/libcxx/include/__ranges/drop_view.h b/libcxx/include/__ranges/drop_view.h
new file mode 100644
index 000000000000..099fd227111d
--- /dev/null
+++ b/libcxx/include/__ranges/drop_view.h
@@ -0,0 +1,131 @@
+// -*- 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_DROP_VIEW_H
+#define _LIBCPP___RANGES_DROP_VIEW_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/next.h>
+#include <__ranges/access.h>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/non_propagating_cache.h>
+#include <__ranges/size.h>
+#include <__ranges/view_interface.h>
+#include <__utility/move.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+ template<view _View>
+ class drop_view
+ : public view_interface<drop_view<_View>>
+ {
+ // We cache begin() whenever ranges::next is not guaranteed O(1) to provide an
+ // amortized O(1) begin() method. If this is an input_range, then we cannot cache
+ // begin because begin is not equality preserving.
+ // Note: drop_view<input-range>::begin() is still trivially amortized O(1) because
+ // one can't call begin() on it more than once.
+ static constexpr bool _UseCache = forward_range<_View> && !(random_access_range<_View> && sized_range<_View>);
+ using _Cache = _If<_UseCache, __non_propagating_cache<iterator_t<_View>>, __empty_cache>;
+ [[no_unique_address]] _Cache __cached_begin_ = _Cache();
+ range_difference_t<_View> __count_ = 0;
+ _View __base_ = _View();
+
+public:
+ drop_view() requires default_initializable<_View> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr drop_view(_View __base, range_difference_t<_View> __count)
+ : __count_(__count)
+ , __base_(_VSTD::move(__base))
+ {
+ _LIBCPP_ASSERT(__count_ >= 0, "count must be greater than or equal to zero.");
+ }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
+ _LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return _VSTD::move(__base_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto begin()
+ requires (!(__simple_view<_View> &&
+ random_access_range<const _View> && sized_range<const _View>))
+ {
+ if constexpr (_UseCache)
+ if (__cached_begin_.__has_value())
+ return *__cached_begin_;
+
+ auto __tmp = ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_));
+ if constexpr (_UseCache)
+ __cached_begin_.__set(__tmp);
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto begin() const
+ requires random_access_range<const _View> && sized_range<const _View>
+ {
+ return ranges::next(ranges::begin(__base_), __count_, ranges::end(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto end()
+ requires (!__simple_view<_View>)
+ { return ranges::end(__base_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto end() const
+ requires range<const _View>
+ { return ranges::end(__base_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ static constexpr auto __size(auto& __self) {
+ const auto __s = ranges::size(__self.__base_);
+ const auto __c = static_cast<decltype(__s)>(__self.__count_);
+ return __s < __c ? 0 : __s - __c;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size()
+ requires sized_range<_View>
+ { return __size(*this); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() const
+ requires sized_range<const _View>
+ { return __size(*this); }
+ };
+
+ template<class _Range>
+ drop_view(_Range&&, range_difference_t<_Range>) -> drop_view<views::all_t<_Range>>;
+
+ template<class _Tp>
+ inline constexpr bool enable_borrowed_range<drop_view<_Tp>> = enable_borrowed_range<_Tp>;
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_DROP_VIEW_H
diff --git a/libcxx/include/__ranges/empty.h b/libcxx/include/__ranges/empty.h
new file mode 100644
index 000000000000..73892a8c1035
--- /dev/null
+++ b/libcxx/include/__ranges/empty.h
@@ -0,0 +1,86 @@
+// -*- 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_EMPTY_H
+#define _LIBCPP___RANGES_EMPTY_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__ranges/access.h>
+#include <__ranges/size.h>
+#include <__utility/forward.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+// clang-format off
+namespace ranges {
+// [range.prim.empty]
+namespace __empty {
+ template <class _Tp>
+ concept __member_empty = requires(_Tp&& __t) {
+ bool(_VSTD::forward<_Tp>(__t).empty());
+ };
+
+ template<class _Tp>
+ concept __can_invoke_size =
+ !__member_empty<_Tp> &&
+ requires(_Tp&& __t) { ranges::size(_VSTD::forward<_Tp>(__t)); };
+
+ template <class _Tp>
+ concept __can_compare_begin_end =
+ !__member_empty<_Tp> &&
+ !__can_invoke_size<_Tp> &&
+ requires(_Tp&& __t) {
+ bool(ranges::begin(__t) == ranges::end(__t));
+ { ranges::begin(__t) } -> forward_iterator;
+ };
+
+ struct __fn {
+ template <__member_empty _Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const
+ noexcept(noexcept(bool(__t.empty()))) {
+ return __t.empty();
+ }
+
+ template <__can_invoke_size _Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::size(_VSTD::forward<_Tp>(__t)))) {
+ return ranges::size(_VSTD::forward<_Tp>(__t)) == 0;
+ }
+
+ template<__can_compare_begin_end _Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool operator()(_Tp&& __t) const
+ noexcept(noexcept(bool(ranges::begin(__t) == ranges::end(__t)))) {
+ return ranges::begin(__t) == ranges::end(__t);
+ }
+ };
+}
+
+inline namespace __cpo {
+ inline constexpr auto empty = __empty::__fn{};
+} // namespace __cpo
+} // namespace ranges
+// clang-format off
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_EMPTY_H
diff --git a/libcxx/include/__ranges/empty_view.h b/libcxx/include/__ranges/empty_view.h
new file mode 100644
index 000000000000..7c0f307c8243
--- /dev/null
+++ b/libcxx/include/__ranges/empty_view.h
@@ -0,0 +1,46 @@
+// -*- 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_EMPTY_VIEW_H
+#define _LIBCPP___RANGES_EMPTY_VIEW_H
+
+#include <__config>
+#include <__ranges/view_interface.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+ template<class _Tp>
+ requires is_object_v<_Tp>
+ class empty_view : public view_interface<empty_view<_Tp>> {
+ public:
+ _LIBCPP_HIDE_FROM_ABI static constexpr _Tp* begin() noexcept { return nullptr; }
+ _LIBCPP_HIDE_FROM_ABI static constexpr _Tp* end() noexcept { return nullptr; }
+ _LIBCPP_HIDE_FROM_ABI static constexpr _Tp* data() noexcept { return nullptr; }
+ _LIBCPP_HIDE_FROM_ABI static constexpr size_t size() noexcept { return 0; }
+ _LIBCPP_HIDE_FROM_ABI static constexpr bool empty() noexcept { return true; }
+ };
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_EMPTY_VIEW_H
diff --git a/libcxx/include/__ranges/enable_borrowed_range.h b/libcxx/include/__ranges/enable_borrowed_range.h
new file mode 100644
index 000000000000..618b2223c716
--- /dev/null
+++ b/libcxx/include/__ranges/enable_borrowed_range.h
@@ -0,0 +1,46 @@
+// -*- C++ -*-
+//===------------------ __ranges/enable_borrowed_range.h ------------------===//
+//
+// 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_ENABLE_BORROWED_RANGE_H
+#define _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H
+
+// These customization variables are used in <span> and <string_view>. The
+// separate header is used to avoid including the entire <ranges> header in
+// <span> and <string_view>.
+
+#include <__config>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges
+{
+
+// [range.range], ranges
+
+template <class>
+inline constexpr bool enable_borrowed_range = false;
+
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_ENABLE_BORROWED_RANGE_H
diff --git a/libcxx/include/__ranges/enable_view.h b/libcxx/include/__ranges/enable_view.h
new file mode 100644
index 000000000000..2628d51ced49
--- /dev/null
+++ b/libcxx/include/__ranges/enable_view.h
@@ -0,0 +1,42 @@
+// -*- 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_ENABLE_VIEW_H
+#define _LIBCPP___RANGES_ENABLE_VIEW_H
+
+#include <__config>
+#include <concepts>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+
+struct view_base { };
+
+template <class _Tp>
+inline constexpr bool enable_view = derived_from<_Tp, view_base>;
+
+} // end namespace ranges
+
+#endif // !_LIBCPP_HAS_NO_RANGES
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_ENABLE_VIEW_H
diff --git a/libcxx/include/__ranges/non_propagating_cache.h b/libcxx/include/__ranges/non_propagating_cache.h
new file mode 100644
index 000000000000..878f7070a07f
--- /dev/null
+++ b/libcxx/include/__ranges/non_propagating_cache.h
@@ -0,0 +1,99 @@
+// -*- 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_NON_PROPAGATING_CACHE_H
+#define _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H
+
+#include <__config>
+#include <__iterator/concepts.h> // indirectly_readable
+#include <__iterator/iterator_traits.h> // iter_reference_t
+#include <__memory/addressof.h>
+#include <concepts> // constructible_from
+#include <optional>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+// clang-format off
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+ // __non_propagating_cache is a helper type that allows storing an optional value in it,
+ // but which does not copy the source's value when it is copy constructed/assigned to,
+ // and which resets the source's value when it is moved-from.
+ //
+ // This type is used as an implementation detail of some views that need to cache the
+ // result of `begin()` in order to provide an amortized O(1) begin() method. Typically,
+ // we don't want to propagate the value of the cache upon copy because the cached iterator
+ // may refer to internal details of the source view.
+ template<class _Tp>
+ requires is_object_v<_Tp>
+ class _LIBCPP_TEMPLATE_VIS __non_propagating_cache {
+ optional<_Tp> __value_ = nullopt;
+
+ public:
+ _LIBCPP_HIDE_FROM_ABI __non_propagating_cache() = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __non_propagating_cache(__non_propagating_cache const&) noexcept
+ : __value_(nullopt)
+ { }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __non_propagating_cache(__non_propagating_cache&& __other) noexcept
+ : __value_(nullopt)
+ {
+ __other.__value_.reset();
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __non_propagating_cache& operator=(__non_propagating_cache const& __other) noexcept {
+ if (this != _VSTD::addressof(__other)) {
+ __value_.reset();
+ }
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __non_propagating_cache& operator=(__non_propagating_cache&& __other) noexcept {
+ __value_.reset();
+ __other.__value_.reset();
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Tp& operator*() { return *__value_; }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Tp const& operator*() const { return *__value_; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr bool __has_value() const { return __value_.has_value(); }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr void __set(_Tp const& __value) { __value_.emplace(__value); }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr void __set(_Tp&& __value) { __value_.emplace(_VSTD::move(__value)); }
+ };
+
+ struct __empty_cache { };
+} // namespace ranges
+
+#endif // _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_NON_PROPAGATING_CACHE_H
diff --git a/libcxx/include/__ranges/ref_view.h b/libcxx/include/__ranges/ref_view.h
new file mode 100644
index 000000000000..fb45a359863b
--- /dev/null
+++ b/libcxx/include/__ranges/ref_view.h
@@ -0,0 +1,87 @@
+// -*- 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_REF_VIEW_H
+#define _LIBCPP___RANGES_REF_VIEW_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iterator_traits.h>
+#include <__memory/addressof.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/data.h>
+#include <__ranges/empty.h>
+#include <__ranges/size.h>
+#include <__ranges/view_interface.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+ template<range _Range>
+ requires is_object_v<_Range>
+ class ref_view : public view_interface<ref_view<_Range>> {
+ _Range *__range_;
+
+ static void __fun(_Range&);
+ static void __fun(_Range&&) = delete;
+
+public:
+ template<class _Tp>
+ requires __different_from<_Tp, ref_view> &&
+ convertible_to<_Tp, _Range&> && requires { __fun(declval<_Tp>()); }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr ref_view(_Tp&& __t)
+ : __range_(_VSTD::addressof(static_cast<_Range&>(_VSTD::forward<_Tp>(__t))))
+ {}
+
+ _LIBCPP_HIDE_FROM_ABI constexpr _Range& base() const { return *__range_; }
+
+ _LIBCPP_HIDE_FROM_ABI constexpr iterator_t<_Range> begin() const { return ranges::begin(*__range_); }
+ _LIBCPP_HIDE_FROM_ABI constexpr sentinel_t<_Range> end() const { return ranges::end(*__range_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr bool empty() const
+ requires requires { ranges::empty(*__range_); }
+ { return ranges::empty(*__range_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() const
+ requires sized_range<_Range>
+ { return ranges::size(*__range_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto data() const
+ requires contiguous_range<_Range>
+ { return ranges::data(*__range_); }
+ };
+
+ template<class _Range>
+ ref_view(_Range&) -> ref_view<_Range>;
+
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_REF_VIEW_H
diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h
new file mode 100644
index 000000000000..ce7183e15447
--- /dev/null
+++ b/libcxx/include/__ranges/size.h
@@ -0,0 +1,132 @@
+// -*- 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_SIZE_H
+#define _LIBCPP___RANGES_SIZE_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__ranges/access.h>
+#include <__utility/__decay_copy.h>
+#include <__utility/forward.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+// clang-format off
+namespace ranges {
+template<class>
+inline constexpr bool disable_sized_range = false;
+
+// [range.prim.size]
+namespace __size {
+ void size(auto&) = delete;
+ void size(const auto&) = delete;
+
+ template <class _Tp>
+ concept __size_enabled = !disable_sized_range<remove_cvref_t<_Tp>>;
+
+ template <class _Tp>
+ concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) {
+ { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).size()) } -> __integer_like;
+ };
+
+ template <class _Tp>
+ concept __unqualified_size =
+ __size_enabled<_Tp> &&
+ !__member_size<_Tp> &&
+ __class_or_enum<remove_cvref_t<_Tp>> &&
+ requires(_Tp&& __t) {
+ { _VSTD::__decay_copy(size(_VSTD::forward<_Tp>(__t))) } -> __integer_like;
+ };
+
+ template <class _Tp>
+ concept __difference =
+ !__member_size<_Tp> &&
+ !__unqualified_size<_Tp> &&
+ __class_or_enum<remove_cvref_t<_Tp>> &&
+ requires(_Tp&& __t) {
+ { ranges::begin(__t) } -> forward_iterator;
+ { ranges::end(__t) } -> sized_sentinel_for<decltype(ranges::begin(declval<_Tp>()))>;
+ };
+
+ struct __fn {
+ template <class _Tp, size_t _Sz>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept {
+ return _Sz;
+ }
+
+ template <class _Tp, size_t _Sz>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept {
+ return _Sz;
+ }
+
+ template <__member_size _Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
+ noexcept(noexcept(_VSTD::forward<_Tp>(__t).size())) {
+ return _VSTD::forward<_Tp>(__t).size();
+ }
+
+ template <__unqualified_size _Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
+ noexcept(noexcept(size(_VSTD::forward<_Tp>(__t)))) {
+ return size(_VSTD::forward<_Tp>(__t));
+ }
+
+ template<__difference _Tp>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr __integer_like auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) {
+ return _VSTD::__to_unsigned_like(ranges::end(__t) - ranges::begin(__t));
+ }
+ };
+} // end namespace __size
+
+inline namespace __cpo {
+ inline constexpr auto size = __size::__fn{};
+} // namespace __cpo
+
+namespace __ssize {
+ struct __fn {
+ template<class _Tp>
+ requires requires (_Tp&& __t) { ranges::size(__t); }
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr integral auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::size(__t))) {
+ using _Signed = make_signed_t<decltype(ranges::size(__t))>;
+ if constexpr (sizeof(ptrdiff_t) > sizeof(_Signed))
+ return static_cast<ptrdiff_t>(ranges::size(__t));
+ else
+ return static_cast<_Signed>(ranges::size(__t));
+ }
+ };
+}
+
+inline namespace __cpo {
+ inline constexpr const auto ssize = __ssize::__fn{};
+} // namespace __cpo
+} // namespace ranges
+
+// clang-format off
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_SIZE_H
diff --git a/libcxx/include/__ranges/subrange.h b/libcxx/include/__ranges/subrange.h
new file mode 100644
index 000000000000..25d333db02de
--- /dev/null
+++ b/libcxx/include/__ranges/subrange.h
@@ -0,0 +1,267 @@
+// -*- 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_SUBRANGE_H
+#define _LIBCPP___RANGES_SUBRANGE_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/incrementable_traits.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/advance.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/dangling.h>
+#include <__ranges/enable_borrowed_range.h>
+#include <__ranges/size.h>
+#include <__ranges/view_interface.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+// clang-format off
+namespace ranges {
+ template<class _From, class _To>
+ concept __convertible_to_non_slicing =
+ convertible_to<_From, _To> &&
+ // If they're both pointers, they must have the same element type.
+ !(is_pointer_v<decay_t<_From>> &&
+ is_pointer_v<decay_t<_To>> &&
+ __different_from<remove_pointer_t<decay_t<_From>>, remove_pointer_t<decay_t<_To>>>);
+
+ template<class _Tp>
+ concept __pair_like =
+ !is_reference_v<_Tp> && requires(_Tp __t) {
+ typename tuple_size<_Tp>::type; // Ensures `tuple_size<T>` is complete.
+ requires derived_from<tuple_size<_Tp>, integral_constant<size_t, 2>>;
+ typename tuple_element_t<0, remove_const_t<_Tp>>;
+ typename tuple_element_t<1, remove_const_t<_Tp>>;
+ { _VSTD::get<0>(__t) } -> convertible_to<const tuple_element_t<0, _Tp>&>;
+ { _VSTD::get<1>(__t) } -> convertible_to<const tuple_element_t<1, _Tp>&>;
+ };
+
+ template<class _Pair, class _Iter, class _Sent>
+ concept __pair_like_convertible_from =
+ !range<_Pair> && __pair_like<_Pair> &&
+ constructible_from<_Pair, _Iter, _Sent> &&
+ __convertible_to_non_slicing<_Iter, tuple_element_t<0, _Pair>> &&
+ convertible_to<_Sent, tuple_element_t<1, _Pair>>;
+
+ enum class _LIBCPP_ENUM_VIS subrange_kind : bool { unsized, sized };
+
+ template<class _Iter, class _Sent, bool>
+ struct __subrange_base {
+ static constexpr bool __store_size = false;
+ _Iter __begin_ = _Iter();
+ _Sent __end_ = _Sent();
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __subrange_base() = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __subrange_base(_Iter __iter, _Sent __sent, make_unsigned_t<iter_difference_t<_Iter>> = 0)
+ : __begin_(_VSTD::move(__iter)), __end_(__sent) { }
+ };
+
+ template<class _Iter, class _Sent>
+ struct __subrange_base<_Iter, _Sent, true> {
+ static constexpr bool __store_size = true;
+ _Iter __begin_ = _Iter();
+ _Sent __end_ = _Sent();
+ make_unsigned_t<iter_difference_t<_Iter>> __size_ = 0;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __subrange_base() = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __subrange_base(_Iter __iter, _Sent __sent, decltype(__size_) __size)
+ : __begin_(_VSTD::move(__iter)), __end_(__sent), __size_(__size) { }
+ };
+
+ template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent = _Iter,
+ subrange_kind _Kind = sized_sentinel_for<_Sent, _Iter>
+ ? subrange_kind::sized
+ : subrange_kind::unsized>
+ requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _Iter>)
+ struct _LIBCPP_TEMPLATE_VIS subrange
+ : public view_interface<subrange<_Iter, _Sent, _Kind>>,
+ private __subrange_base<_Iter, _Sent, _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>> {
+
+ using _Base = __subrange_base<_Iter, _Sent, _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _Iter>>;
+
+ _LIBCPP_HIDE_FROM_ABI
+ subrange() requires default_initializable<_Iter> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent)
+ requires (!_Base::__store_size)
+ : _Base(_VSTD::move(__iter), __sent) {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr subrange(__convertible_to_non_slicing<_Iter> auto __iter, _Sent __sent,
+ make_unsigned_t<iter_difference_t<_Iter>> __n)
+ requires (_Kind == subrange_kind::sized)
+ : _Base(_VSTD::move(__iter), __sent, __n) { }
+
+ template<__different_from<subrange> _Range>
+ requires borrowed_range<_Range> &&
+ __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
+ convertible_to<sentinel_t<_Range>, _Sent>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr subrange(_Range&& __range)
+ requires (!_Base::__store_size)
+ : subrange(ranges::begin(__range), ranges::end(__range)) { }
+
+ template<__different_from<subrange> _Range>
+ requires borrowed_range<_Range> &&
+ __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
+ convertible_to<sentinel_t<_Range>, _Sent>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr subrange(_Range&& __range)
+ requires _Base::__store_size && sized_range<_Range>
+ : subrange(__range, ranges::size(__range)) { }
+
+
+ template<borrowed_range _Range>
+ requires __convertible_to_non_slicing<iterator_t<_Range>, _Iter> &&
+ convertible_to<sentinel_t<_Range>, _Sent>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr subrange(_Range&& __range, make_unsigned_t<iter_difference_t<_Iter>> __n)
+ requires (_Kind == subrange_kind::sized)
+ : subrange(ranges::begin(__range), ranges::end(__range), __n) { }
+
+ template<__different_from<subrange> _Pair>
+ requires __pair_like_convertible_from<_Pair, const _Iter&, const _Sent&>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr operator _Pair() const { return _Pair(this->__begin_, this->__end_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Iter begin() const requires copyable<_Iter> {
+ return this->__begin_;
+ }
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Iter begin() requires (!copyable<_Iter>) {
+ return _VSTD::move(this->__begin_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Sent end() const { return this->__end_; }
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return this->__begin_ == this->__end_; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr make_unsigned_t<iter_difference_t<_Iter>> size() const
+ requires (_Kind == subrange_kind::sized)
+ {
+ if constexpr (_Base::__store_size)
+ return this->__size_;
+ else
+ return __to_unsigned_like(this->__end_ - this->__begin_);
+ }
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) const&
+ requires forward_iterator<_Iter> {
+ auto __tmp = *this;
+ __tmp.advance(__n);
+ return __tmp;
+ }
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange next(iter_difference_t<_Iter> __n = 1) && {
+ advance(__n);
+ return _VSTD::move(*this);
+ }
+
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr subrange prev(iter_difference_t<_Iter> __n = 1) const
+ requires bidirectional_iterator<_Iter> {
+ auto __tmp = *this;
+ __tmp.advance(-__n);
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr subrange& advance(iter_difference_t<_Iter> __n) {
+ if constexpr (bidirectional_iterator<_Iter>) {
+ if (__n < 0) {
+ ranges::advance(this->__begin_, __n);
+ if constexpr (_Base::__store_size)
+ this->__size_ += _VSTD::__to_unsigned_like(-__n);
+ return *this;
+ }
+ }
+
+ auto __d = __n - ranges::advance(this->__begin_, __n, this->__end_);
+ if constexpr (_Base::__store_size)
+ this->__size_ -= _VSTD::__to_unsigned_like(__d);
+ return *this;
+ }
+ };
+
+ template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
+ subrange(_Iter, _Sent) -> subrange<_Iter, _Sent>;
+
+ template<input_or_output_iterator _Iter, sentinel_for<_Iter> _Sent>
+ subrange(_Iter, _Sent, make_unsigned_t<iter_difference_t<_Iter>>)
+ -> subrange<_Iter, _Sent, subrange_kind::sized>;
+
+ template<borrowed_range _Range>
+ subrange(_Range&&) -> subrange<iterator_t<_Range>, sentinel_t<_Range>,
+ (sized_range<_Range> || sized_sentinel_for<sentinel_t<_Range>, iterator_t<_Range>>)
+ ? subrange_kind::sized : subrange_kind::unsized>;
+
+ template<borrowed_range _Range>
+ subrange(_Range&&, make_unsigned_t<range_difference_t<_Range>>)
+ -> subrange<iterator_t<_Range>, sentinel_t<_Range>, subrange_kind::sized>;
+
+ template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
+ requires (_Index < 2)
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto get(const subrange<_Iter, _Sent, _Kind>& __subrange) {
+ if constexpr (_Index == 0)
+ return __subrange.begin();
+ else
+ return __subrange.end();
+ }
+
+ template<size_t _Index, class _Iter, class _Sent, subrange_kind _Kind>
+ requires (_Index < 2)
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto get(subrange<_Iter, _Sent, _Kind>&& __subrange) {
+ if constexpr (_Index == 0)
+ return __subrange.begin();
+ else
+ return __subrange.end();
+ }
+
+ template<class _Ip, class _Sp, subrange_kind _Kp>
+ inline constexpr bool enable_borrowed_range<subrange<_Ip, _Sp, _Kp>> = true;
+
+ template<range _Rp>
+ using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp> >, dangling>;
+} // namespace ranges
+
+using ranges::get;
+
+// clang-format off
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_SUBRANGE_H
diff --git a/libcxx/include/__ranges/transform_view.h b/libcxx/include/__ranges/transform_view.h
new file mode 100644
index 000000000000..4243dc0366e9
--- /dev/null
+++ b/libcxx/include/__ranges/transform_view.h
@@ -0,0 +1,408 @@
+// -*- 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_TRANSFORM_VIEW_H
+#define _LIBCPP___RANGES_TRANSFORM_VIEW_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iter_swap.h>
+#include <__iterator/iterator_traits.h>
+#include <__ranges/access.h>
+#include <__ranges/all.h>
+#include <__ranges/concepts.h>
+#include <__ranges/copyable_box.h>
+#include <__ranges/empty.h>
+#include <__ranges/size.h>
+#include <__ranges/view_interface.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+
+template<class _View, class _Fn>
+concept __transform_view_constraints =
+ view<_View> && is_object_v<_Fn> &&
+ regular_invocable<_Fn&, range_reference_t<_View>> &&
+ __referenceable<invoke_result_t<_Fn&, range_reference_t<_View>>>;
+
+template<input_range _View, copy_constructible _Fn>
+ requires __transform_view_constraints<_View, _Fn>
+class transform_view : public view_interface<transform_view<_View, _Fn>> {
+ template<bool> class __iterator;
+ template<bool> class __sentinel;
+
+ [[no_unique_address]] __copyable_box<_Fn> __func_;
+ [[no_unique_address]] _View __base_ = _View();
+
+public:
+ _LIBCPP_HIDE_FROM_ABI
+ transform_view()
+ requires default_initializable<_View> && default_initializable<_Fn> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr transform_view(_View __base, _Fn __func)
+ : __func_(_VSTD::in_place, _VSTD::move(__func)), __base_(_VSTD::move(__base)) {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _View base() const& requires copy_constructible<_View> { return __base_; }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _View base() && { return _VSTD::move(__base_); }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator<false> begin() {
+ return __iterator<false>{*this, ranges::begin(__base_)};
+ }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator<true> begin() const
+ requires range<const _View> &&
+ regular_invocable<const _Fn&, range_reference_t<const _View>>
+ {
+ return __iterator<true>(*this, ranges::begin(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __sentinel<false> end() {
+ return __sentinel<false>(ranges::end(__base_));
+ }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator<false> end()
+ requires common_range<_View>
+ {
+ return __iterator<false>(*this, ranges::end(__base_));
+ }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __sentinel<true> end() const
+ requires range<const _View> &&
+ regular_invocable<const _Fn&, range_reference_t<const _View>>
+ {
+ return __sentinel<true>(ranges::end(__base_));
+ }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator<true> end() const
+ requires common_range<const _View> &&
+ regular_invocable<const _Fn&, range_reference_t<const _View>>
+ {
+ return __iterator<true>(*this, ranges::end(__base_));
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() requires sized_range<_View> { return ranges::size(__base_); }
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() const requires sized_range<const _View> { return ranges::size(__base_); }
+};
+
+template<class _Range, class _Fn>
+transform_view(_Range&&, _Fn) -> transform_view<views::all_t<_Range>, _Fn>;
+
+template<class _View>
+struct __transform_view_iterator_concept { using type = input_iterator_tag; };
+
+template<random_access_range _View>
+struct __transform_view_iterator_concept<_View> { using type = random_access_iterator_tag; };
+
+template<bidirectional_range _View>
+struct __transform_view_iterator_concept<_View> { using type = bidirectional_iterator_tag; };
+
+template<forward_range _View>
+struct __transform_view_iterator_concept<_View> { using type = forward_iterator_tag; };
+
+template<class, class>
+struct __transform_view_iterator_category_base {};
+
+template<forward_range _View, class _Fn>
+struct __transform_view_iterator_category_base<_View, _Fn> {
+ using _Cat = typename iterator_traits<iterator_t<_View>>::iterator_category;
+
+ using iterator_category = conditional_t<
+ is_lvalue_reference_v<invoke_result_t<_Fn&, range_reference_t<_View>>>,
+ conditional_t<
+ derived_from<_Cat, contiguous_iterator_tag>,
+ random_access_iterator_tag,
+ _Cat
+ >,
+ input_iterator_tag
+ >;
+};
+
+template<input_range _View, copy_constructible _Fn>
+ requires __transform_view_constraints<_View, _Fn>
+template<bool _Const>
+class transform_view<_View, _Fn>::__iterator
+ : public __transform_view_iterator_category_base<_View, _Fn> {
+
+ using _Parent = __maybe_const<_Const, transform_view>;
+ using _Base = __maybe_const<_Const, _View>;
+
+ _Parent *__parent_ = nullptr;
+
+ template<bool>
+ friend class transform_view<_View, _Fn>::__iterator;
+
+ template<bool>
+ friend class transform_view<_View, _Fn>::__sentinel;
+
+public:
+ iterator_t<_Base> __current_ = iterator_t<_Base>();
+
+ using iterator_concept = typename __transform_view_iterator_concept<_View>::type;
+ using value_type = remove_cvref_t<invoke_result_t<_Fn&, range_reference_t<_Base>>>;
+ using difference_type = range_difference_t<_Base>;
+
+ _LIBCPP_HIDE_FROM_ABI
+ __iterator() requires default_initializable<iterator_t<_Base>> = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator(_Parent& __parent, iterator_t<_Base> __current)
+ : __parent_(_VSTD::addressof(__parent)), __current_(_VSTD::move(__current)) {}
+
+ // Note: `__i` should always be `__iterator<false>`, but directly using
+ // `__iterator<false>` is ill-formed when `_Const` is false
+ // (see http://wg21.link/class.copy.ctor#5).
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator(__iterator<!_Const> __i)
+ requires _Const && convertible_to<iterator_t<_View>, iterator_t<_Base>>
+ : __parent_(__i.__parent_), __current_(_VSTD::move(__i.__current_)) {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr iterator_t<_Base> base() const&
+ requires copyable<iterator_t<_Base>>
+ {
+ return __current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr iterator_t<_Base> base() && {
+ return _VSTD::move(__current_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) operator*() const
+ noexcept(noexcept(_VSTD::invoke(*__parent_->__func_, *__current_)))
+ {
+ return _VSTD::invoke(*__parent_->__func_, *__current_);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator& operator++() {
+ ++__current_;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr void operator++(int) { ++__current_; }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator operator++(int)
+ requires forward_range<_Base>
+ {
+ auto __tmp = *this;
+ ++*this;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator& operator--()
+ requires bidirectional_range<_Base>
+ {
+ --__current_;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator operator--(int)
+ requires bidirectional_range<_Base>
+ {
+ auto __tmp = *this;
+ --*this;
+ return __tmp;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator& operator+=(difference_type __n)
+ requires random_access_range<_Base>
+ {
+ __current_ += __n;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __iterator& operator-=(difference_type __n)
+ requires random_access_range<_Base>
+ {
+ __current_ -= __n;
+ return *this;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) operator[](difference_type __n) const
+ noexcept(noexcept(_VSTD::invoke(*__parent_->__func_, __current_[__n])))
+ requires random_access_range<_Base>
+ {
+ return _VSTD::invoke(*__parent_->__func_, __current_[__n]);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
+ requires equality_comparable<iterator_t<_Base>>
+ {
+ return __x.__current_ == __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return __x.__current_ < __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return __x.__current_ > __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return __x.__current_ <= __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
+ requires random_access_range<_Base>
+ {
+ return __x.__current_ >= __y.__current_;
+ }
+
+// TODO: Fix this as soon as soon as three_way_comparable is implemented.
+// _LIBCPP_HIDE_FROM_ABI
+// friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
+// requires random_access_range<_Base> && three_way_comparable<iterator_t<_Base>>
+// {
+// return __x.__current_ <=> __y.__current_;
+// }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr __iterator operator+(__iterator __i, difference_type __n)
+ requires random_access_range<_Base>
+ {
+ return __iterator{*__i.__parent_, __i.__current_ + __n};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr __iterator operator+(difference_type __n, __iterator __i)
+ requires random_access_range<_Base>
+ {
+ return __iterator{*__i.__parent_, __i.__current_ + __n};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr __iterator operator-(__iterator __i, difference_type __n)
+ requires random_access_range<_Base>
+ {
+ return __iterator{*__i.__parent_, __i.__current_ - __n};
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
+ requires sized_sentinel_for<iterator_t<_Base>, iterator_t<_Base>>
+ {
+ return __x.__current_ - __y.__current_;
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr decltype(auto) iter_move(const __iterator& __i)
+ noexcept(noexcept(*__i))
+ {
+ if constexpr (is_lvalue_reference_v<decltype(*__i)>)
+ return _VSTD::move(*__i);
+ else
+ return *__i;
+ }
+};
+
+template<input_range _View, copy_constructible _Fn>
+ requires __transform_view_constraints<_View, _Fn>
+template<bool _Const>
+class transform_view<_View, _Fn>::__sentinel {
+ using _Parent = __maybe_const<_Const, transform_view>;
+ using _Base = __maybe_const<_Const, _View>;
+
+ sentinel_t<_Base> __end_ = sentinel_t<_Base>();
+
+ template<bool>
+ friend class transform_view<_View, _Fn>::__iterator;
+
+ template<bool>
+ friend class transform_view<_View, _Fn>::__sentinel;
+
+public:
+ _LIBCPP_HIDE_FROM_ABI
+ __sentinel() = default;
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit __sentinel(sentinel_t<_Base> __end) : __end_(__end) {}
+
+ // Note: `__i` should always be `__sentinel<false>`, but directly using
+ // `__sentinel<false>` is ill-formed when `_Const` is false
+ // (see http://wg21.link/class.copy.ctor#5).
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr __sentinel(__sentinel<!_Const> __i)
+ requires _Const && convertible_to<sentinel_t<_View>, sentinel_t<_Base>>
+ : __end_(_VSTD::move(__i.__end_)) {}
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr sentinel_t<_Base> base() const { return __end_; }
+
+ template<bool _OtherConst>
+ requires sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
+ return __x.__current_ == __y.__end_;
+ }
+
+ template<bool _OtherConst>
+ requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
+ operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
+ return __x.__current_ - __y.__end_;
+ }
+
+ template<bool _OtherConst>
+ requires sized_sentinel_for<sentinel_t<_Base>, iterator_t<__maybe_const<_OtherConst, _View>>>
+ _LIBCPP_HIDE_FROM_ABI
+ friend constexpr range_difference_t<__maybe_const<_OtherConst, _View>>
+ operator-(const __sentinel& __x, const __iterator<_OtherConst>& __y) {
+ return __x.__end_ - __y.__current_;
+ }
+};
+
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_TRANSFORM_VIEW_H
diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h
new file mode 100644
index 000000000000..62cc5fd24362
--- /dev/null
+++ b/libcxx/include/__ranges/view_interface.h
@@ -0,0 +1,198 @@
+// -*- 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_VIEW_INTERFACE_H
+#define _LIBCPP___RANGES_VIEW_INTERFACE_H
+
+#include <__config>
+#include <__iterator/concepts.h>
+#include <__iterator/iterator_traits.h>
+#include <__iterator/prev.h>
+#include <__memory/pointer_traits.h>
+#include <__ranges/access.h>
+#include <__ranges/concepts.h>
+#include <__ranges/empty.h>
+#include <__ranges/enable_view.h>
+#include <concepts>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+
+template<class _Tp>
+concept __can_empty = requires(_Tp __t) { ranges::empty(__t); };
+
+template<class _Tp>
+void __implicitly_convert_to(type_identity_t<_Tp>) noexcept;
+
+template<class _Derived>
+ requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
+class view_interface : public view_base {
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Derived& __derived() noexcept {
+ return static_cast<_Derived&>(*this);
+ }
+
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr _Derived const& __derived() const noexcept {
+ return static_cast<_Derived const&>(*this);
+ }
+
+public:
+ template<class _D2 = _Derived>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
+ noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
+ requires forward_range<_D2>
+ {
+ return ranges::begin(__derived()) == ranges::end(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
+ noexcept(noexcept(__implicitly_convert_to<bool>(ranges::begin(__derived()) == ranges::end(__derived()))))
+ requires forward_range<const _D2>
+ {
+ return ranges::begin(__derived()) == ranges::end(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit operator bool()
+ noexcept(noexcept(ranges::empty(declval<_D2>())))
+ requires __can_empty<_D2>
+ {
+ return !ranges::empty(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr explicit operator bool() const
+ noexcept(noexcept(ranges::empty(declval<const _D2>())))
+ requires __can_empty<const _D2>
+ {
+ return !ranges::empty(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto data()
+ noexcept(noexcept(_VSTD::to_address(ranges::begin(__derived()))))
+ requires contiguous_iterator<iterator_t<_D2>>
+ {
+ return _VSTD::to_address(ranges::begin(__derived()));
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto data() const
+ noexcept(noexcept(_VSTD::to_address(ranges::begin(__derived()))))
+ requires range<const _D2> && contiguous_iterator<iterator_t<const _D2>>
+ {
+ return _VSTD::to_address(ranges::begin(__derived()));
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size()
+ noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
+ requires forward_range<_D2>
+ && sized_sentinel_for<sentinel_t<_D2>, iterator_t<_D2>>
+ {
+ return ranges::end(__derived()) - ranges::begin(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr auto size() const
+ noexcept(noexcept(ranges::end(__derived()) - ranges::begin(__derived())))
+ requires forward_range<const _D2>
+ && sized_sentinel_for<sentinel_t<const _D2>, iterator_t<const _D2>>
+ {
+ return ranges::end(__derived()) - ranges::begin(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) front()
+ noexcept(noexcept(*ranges::begin(__derived())))
+ requires forward_range<_D2>
+ {
+ _LIBCPP_ASSERT(!empty(),
+ "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
+ return *ranges::begin(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) front() const
+ noexcept(noexcept(*ranges::begin(__derived())))
+ requires forward_range<const _D2>
+ {
+ _LIBCPP_ASSERT(!empty(),
+ "Precondition `!empty()` not satisfied. `.front()` called on an empty view.");
+ return *ranges::begin(__derived());
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) back()
+ noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
+ requires bidirectional_range<_D2> && common_range<_D2>
+ {
+ _LIBCPP_ASSERT(!empty(),
+ "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
+ return *ranges::prev(ranges::end(__derived()));
+ }
+
+ template<class _D2 = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) back() const
+ noexcept(noexcept(*ranges::prev(ranges::end(__derived()))))
+ requires bidirectional_range<const _D2> && common_range<const _D2>
+ {
+ _LIBCPP_ASSERT(!empty(),
+ "Precondition `!empty()` not satisfied. `.back()` called on an empty view.");
+ return *ranges::prev(ranges::end(__derived()));
+ }
+
+ template<random_access_range _RARange = _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) operator[](range_difference_t<_RARange> __index)
+ noexcept(noexcept(ranges::begin(__derived())[__index]))
+ {
+ return ranges::begin(__derived())[__index];
+ }
+
+ template<random_access_range _RARange = const _Derived>
+ _LIBCPP_HIDE_FROM_ABI
+ constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const
+ noexcept(noexcept(ranges::begin(__derived())[__index]))
+ {
+ return ranges::begin(__derived())[__index];
+ }
+};
+
+}
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
+_LIBCPP_END_NAMESPACE_STD
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_VIEW_INTERFACE_H