#ifndef _LIBCPP___RANGES_SUBRANGE_H
#define _LIBCPP___RANGES_SUBRANGE_H
+#include <__concepts/constructible.h>
+#include <__concepts/convertible_to.h>
+#include <__concepts/copyable.h>
+#include <__concepts/derived_from.h>
+#include <__concepts/different_from.h>
#include <__config>
#include <__iterator/concepts.h>
#include <__iterator/incrementable_traits.h>
#include <__ranges/view_interface.h>
#include <__tuple>
#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)
-// clang-format off
namespace ranges {
template<class _From, class _To>
concept __convertible_to_non_slicing =
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>;
+ using borrowed_subrange_t = _If<borrowed_range<_Rp>, subrange<iterator_t<_Rp>>, dangling>;
} // namespace ranges
+// [range.subrange.general]
+
using ranges::get;
-// clang-format off
+// [ranges.syn]
+
+template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_size<ranges::subrange<_Ip, _Sp, _Kp>> : integral_constant<size_t, 2> {};
+
+template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_element<0, ranges::subrange<_Ip, _Sp, _Kp>> {
+ using type = _Ip;
+};
+
+template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_element<1, ranges::subrange<_Ip, _Sp, _Kp>> {
+ using type = _Sp;
+};
+
+template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_element<0, const ranges::subrange<_Ip, _Sp, _Kp>> {
+ using type = _Ip;
+};
+
+template<class _Ip, class _Sp, ranges::subrange_kind _Kp>
+struct tuple_element<1, const ranges::subrange<_Ip, _Sp, _Kp>> {
+ using type = _Sp;
+};
#endif // !defined(_LIBCPP_HAS_NO_RANGES)
_LIBCPP_END_NAMESPACE_STD
-_LIBCPP_POP_MACROS
-
#endif // _LIBCPP___RANGES_SUBRANGE_H
--- /dev/null
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: libcpp-has-no-incomplete-ranges
+
+// class std::ranges::subrange;
+
+#include <ranges>
+
+#include <cassert>
+#include "test_macros.h"
+
+constexpr void test_sized_subrange()
+{
+ int a[4] = {1,2,3,4};
+ auto r = std::ranges::subrange(a, a+4);
+ assert(std::ranges::sized_range<decltype(r)>);
+ {
+ auto [first, last] = r;
+ assert(first == a);
+ assert(last == a+4);
+ }
+ {
+ auto [first, last] = std::move(r);
+ assert(first == a);
+ assert(last == a+4);
+ }
+ {
+ auto [first, last] = std::as_const(r);
+ assert(first == a);
+ assert(last == a+4);
+ }
+ {
+ auto [first, last] = std::move(std::as_const(r));
+ assert(first == a);
+ assert(last == a+4);
+ }
+}
+
+constexpr void test_unsized_subrange()
+{
+ int a[4] = {1,2,3,4};
+ auto r = std::ranges::subrange(a, std::unreachable_sentinel);
+ assert(!std::ranges::sized_range<decltype(r)>);
+ {
+ auto [first, last] = r;
+ assert(first == a);
+ ASSERT_SAME_TYPE(decltype(last), std::unreachable_sentinel_t);
+ }
+ {
+ auto [first, last] = std::move(r);
+ assert(first == a);
+ ASSERT_SAME_TYPE(decltype(last), std::unreachable_sentinel_t);
+ }
+ {
+ auto [first, last] = std::as_const(r);
+ assert(first == a);
+ ASSERT_SAME_TYPE(decltype(last), std::unreachable_sentinel_t);
+ }
+ {
+ auto [first, last] = std::move(std::as_const(r));
+ assert(first == a);
+ ASSERT_SAME_TYPE(decltype(last), std::unreachable_sentinel_t);
+ }
+}
+
+constexpr void test_copies_not_originals()
+{
+ int a[4] = {1,2,3,4};
+ {
+ auto r = std::ranges::subrange(a, a+4);
+ auto&& [first, last] = r;
+ ASSERT_SAME_TYPE(decltype(first), int*);
+ ASSERT_SAME_TYPE(decltype(last), int*);
+ first = a+2;
+ last = a+2;
+ assert(r.begin() == a);
+ assert(r.end() == a+4);
+ }
+ {
+ const auto r = std::ranges::subrange(a, a+4);
+ auto&& [first, last] = r;
+ ASSERT_SAME_TYPE(decltype(first), int*);
+ ASSERT_SAME_TYPE(decltype(last), int*);
+ first = a+2;
+ last = a+2;
+ assert(r.begin() == a);
+ assert(r.end() == a+4);
+ }
+}
+
+constexpr bool test()
+{
+ test_sized_subrange();
+ test_unsized_subrange();
+ test_copies_not_originals();
+ return true;
+}
+
+int main(int, char**)
+{
+ test();
+ static_assert(test());
+
+ return 0;
+}