| `ranges::bidirectional_range <https://llvm.org/D100278>`_
| `ranges::random_access_range <https://llvm.org/D101316>`_
| ranges::contiguous_range
-| `ranges::common_range <https://llvm.org/D100269>`_
-| ranges::viewable_range",[range.range],Christopher Di Bella,In progress
+| `ranges::common_range <https://llvm.org/D100269>`_",[range.range],Christopher Di Bella,✅
+`[range.refinements]`_,`ranges::viewable_range <https://reviews.llvm.org/D105816>`_,[range.range],Louis Dionne,✅
`[range.utility.helpers] <http://wg21.link/range.utility.helpers>`_,"| *simple-view*
| *has-arrow*
| *not-same-as*","| [range.range]
#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>
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)
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)
};
template<class _Range>
- drop_view(_Range&&, range_difference_t<_Range>)
- // TODO: this is just recreating all_t.
- -> drop_view<decltype(views::all(std::declval<_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>;
#define _LIBCPP___RANGES_TRANSFORM_VIEW_H
#include <__config>
-#include <__iterator/iterator_traits.h>
#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>
constexpr auto size() const requires sized_range<const _View> { return ranges::size(__base_); }
};
-// TODO: replace the decltype with all_t when that's implemented.
template<class _Range, class _Fn>
-transform_view(_Range&&, _Fn)
- -> transform_view<decltype(views::all(std::declval<_Range>())), _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<range R>
using range_rvalue_reference_t = iter_rvalue_reference_t<iterator_t<R>>;
- // [range.sized]
+ // [range.sized], sized ranges
template<class>
inline constexpr bool disable_sized_range = false;
template <class _Tp>
concept common_range = see below;
+ template<class T>
+ concept viewable_range = see below;
+
// [view.interface], class template view_interface
template<class D>
requires is_class_v<D> && same_as<D, remove_cv_t<D>>
requires is_object_v<T>
class empty_view;
+ // [range.all], all view
+ namespace views {
+ inline constexpr unspecified all = unspecified;
+
+ template<viewable_range R>
+ using all_t = decltype(all(declval<R>()));
+ }
+
+ template<range R>
+ requires is_object_v<R>
+ class ref_view;
+
+ template<class T>
+ inline constexpr bool enable_borrowed_range<ref_view<T>> = true;
+
// [range.drop], drop view
template<view V>
class drop_view;
static_assert(!stdr::random_access_range<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::random_access_range<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::random_access_range<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::random_access_range<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::random_access_range<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::random_access_range<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::bidirectional_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(stdr::contiguous_range<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(!stdr::view<range const>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::contiguous_range<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(!stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(!stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::random_access_range<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::random_access_range<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(!stdr::view<range>);
static_assert(stdr::sized_range<range>);
static_assert(!stdr::borrowed_range<range>);
+static_assert(!stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::const_iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(!stdr::borrowed_range<range const>);
+static_assert(!stdr::viewable_range<range const>);
static_assert(stdr::view<range> && stdr::enable_view<range>);
static_assert(stdr::sized_range<range>);
static_assert(stdr::borrowed_range<range>);
+static_assert(stdr::viewable_range<range>);
static_assert(std::same_as<stdr::iterator_t<range const>, range::iterator>);
static_assert(stdr::common_range<range const>);
static_assert(!stdr::view<range const> && !stdr::enable_view<range const>);
static_assert(stdr::sized_range<range const>);
static_assert(stdr::borrowed_range<range const>);
+static_assert(stdr::viewable_range<range const>);
static_assert(!stdr::view<fs::directory_iterator>);
static_assert(!stdr::sized_range<fs::directory_iterator>);
static_assert(!stdr::borrowed_range<fs::directory_iterator>);
+static_assert(!stdr::viewable_range<fs::directory_iterator>);
static_assert(std::same_as<stdr::iterator_t<fs::directory_iterator const>, fs::directory_iterator>);
static_assert(stdr::common_range<fs::directory_iterator const>);
static_assert(!stdr::view<fs::directory_iterator const>);
static_assert(!stdr::sized_range<fs::directory_iterator const>);
static_assert(!stdr::borrowed_range<fs::directory_iterator const>);
+static_assert(!stdr::viewable_range<fs::directory_iterator const>);
static_assert(std::same_as<stdr::iterator_t<fs::recursive_directory_iterator>, fs::recursive_directory_iterator>);
static_assert(stdr::common_range<fs::recursive_directory_iterator>);
static_assert(!stdr::view<fs::recursive_directory_iterator>);
static_assert(!stdr::sized_range<fs::recursive_directory_iterator>);
static_assert(!stdr::borrowed_range<fs::recursive_directory_iterator>);
+static_assert(!stdr::viewable_range<fs::recursive_directory_iterator>);
static_assert(std::same_as<stdr::iterator_t<fs::recursive_directory_iterator const>, fs::recursive_directory_iterator>);
static_assert(stdr::common_range<fs::recursive_directory_iterator const>);
static_assert(!stdr::view<fs::recursive_directory_iterator const>);
static_assert(!stdr::sized_range<fs::recursive_directory_iterator const>);
static_assert(!stdr::borrowed_range<fs::recursive_directory_iterator const>);
+static_assert(!stdr::viewable_range<fs::recursive_directory_iterator const>);
static_assert(!stdr::random_access_range<fs::path>);
static_assert(!stdr::sized_range<fs::path>);
static_assert(!stdr::borrowed_range<fs::path>);
+static_assert(!stdr::viewable_range<fs::path>);
static_assert(std::same_as<stdr::iterator_t<fs::path const>, fs::path::const_iterator>);
static_assert(stdr::common_range<fs::path const>);
static_assert(!stdr::random_access_range<fs::path const>);
static_assert(!stdr::sized_range<fs::path const>);
static_assert(!stdr::borrowed_range<fs::path const>);
+static_assert(!stdr::viewable_range<fs::path const>);
--- /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: gcc-10
+
+// template<viewable_range R>
+// using all_t = decltype(views::all(declval<R>()));
+
+#include <ranges>
+
+#include "test_iterators.h"
+#include "test_range.h"
+
+struct View : test_range<cpp20_input_iterator>, std::ranges::view_base { };
+struct Range : test_range<cpp20_input_iterator> { };
+struct BorrowableRange : test_range<forward_iterator> { };
+template<>
+inline constexpr bool std::ranges::enable_borrowed_range<BorrowableRange> = true;
+
+// When T is a view, returns decay-copy(T)
+ASSERT_SAME_TYPE(std::views::all_t<View>, View);
+ASSERT_SAME_TYPE(std::views::all_t<View&>, View);
+ASSERT_SAME_TYPE(std::views::all_t<View const>, View);
+ASSERT_SAME_TYPE(std::views::all_t<View const&>, View);
+
+// Otherwise, when T is a reference to a range, returns ref_view<T>
+ASSERT_SAME_TYPE(std::views::all_t<Range&>, std::ranges::ref_view<Range>);
+ASSERT_SAME_TYPE(std::views::all_t<Range const&>, std::ranges::ref_view<Range const>);
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange&>, std::ranges::ref_view<BorrowableRange>);
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange const&>, std::ranges::ref_view<BorrowableRange const>);
+
+// Otherwise, returns subrange<iterator_t<T>, sentinel_t<R>>
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange>, std::ranges::subrange<forward_iterator<int*>, sentinel>);
+ASSERT_SAME_TYPE(std::views::all_t<BorrowableRange const>, std::ranges::subrange<forward_iterator<int const*>, sentinel>);
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: gcc-10
-// std::ranges::ref_view
+// template<range R>
+// requires is_object_v<R>
+// class ref_view;
#include <ranges>
--- /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: gcc-10
+
+// template<class R>
+// concept viewable_range;
+
+#include <ranges>
+#include <type_traits>
+
+#include "test_iterators.h"
+#include "test_range.h"
+
+// The constraints we have in viewable_range are:
+// range<T>
+// view<remove_cvref_t<T>>
+// constructible_from<remove_cvref_t<T>, T>
+// borrowed_range<T>
+//
+// We test all the relevant combinations of satisfying/not satisfying those constraints.
+
+// viewable_range<T> is not satisfied for (range=false, view=*, constructible_from=*, borrowed_range=*)
+struct T1 { };
+static_assert(!std::ranges::range<T1>);
+
+static_assert(!std::ranges::viewable_range<T1>);
+static_assert(!std::ranges::viewable_range<T1&>);
+static_assert(!std::ranges::viewable_range<T1 const>);
+static_assert(!std::ranges::viewable_range<T1 const&>);
+
+// viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=true)
+struct T2 : test_range<cpp20_input_iterator>, std::ranges::view_base {
+ T2(T2 const&) = default;
+};
+template<> constexpr bool std::ranges::enable_borrowed_range<T2> = true;
+static_assert(std::ranges::range<T2>);
+static_assert(std::ranges::view<T2>);
+static_assert(std::constructible_from<T2, T2>);
+static_assert(std::ranges::borrowed_range<T2>);
+
+static_assert(std::ranges::viewable_range<T2>);
+static_assert(std::ranges::viewable_range<T2&>);
+static_assert(std::ranges::viewable_range<T2 const>);
+static_assert(std::ranges::viewable_range<T2 const&>);
+
+// viewable_range<T> is satisfied for (range=true, view=true, constructible_from=true, borrowed_range=false)
+struct T3 : test_range<cpp20_input_iterator>, std::ranges::view_base {
+ T3(T3 const&) = default;
+};
+template<> constexpr bool std::ranges::enable_borrowed_range<T3> = false;
+static_assert(std::ranges::range<T3>);
+static_assert(std::ranges::view<T3>);
+static_assert(std::constructible_from<T3, T3>);
+static_assert(!std::ranges::borrowed_range<T3>);
+
+static_assert(std::ranges::viewable_range<T3>);
+static_assert(std::ranges::viewable_range<T3&>);
+static_assert(std::ranges::viewable_range<T3 const>);
+static_assert(std::ranges::viewable_range<T3 const&>);
+
+// viewable_range<T> is not satisfied for (range=true, view=true, constructible_from=false, borrowed_range=true)
+struct T4 : test_range<cpp20_input_iterator>, std::ranges::view_base {
+ T4(T4 const&) = delete;
+ T4(T4&&) = default; // necessary to model view
+ T4& operator=(T4&&) = default; // necessary to model view
+};
+static_assert(std::ranges::range<T4 const&>);
+static_assert(std::ranges::view<std::remove_cvref_t<T4 const&>>);
+static_assert(!std::constructible_from<std::remove_cvref_t<T4 const&>, T4 const&>);
+static_assert(std::ranges::borrowed_range<T4 const&>);
+
+static_assert(!std::ranges::viewable_range<T4 const&>);
+
+// A type that satisfies (range=true, view=true, constructible_from=false, borrowed_range=false) can't be formed
+
+// viewable_range<T> is satisfied for (range=true, view=false, constructible_from=true, borrowed_range=true)
+struct T5 : test_range<cpp20_input_iterator> { };
+template<> constexpr bool std::ranges::enable_borrowed_range<T5> = true;
+static_assert(std::ranges::range<T5>);
+static_assert(!std::ranges::view<T5>);
+static_assert(std::constructible_from<T5, T5>);
+static_assert(std::ranges::borrowed_range<T5>);
+
+static_assert(std::ranges::viewable_range<T5>);
+
+// viewable_range<T> is not satisfied for (range=true, view=false, constructible_from=true, borrowed_range=false)
+struct T6 : test_range<cpp20_input_iterator> { };
+template<> constexpr bool std::ranges::enable_borrowed_range<T6> = false;
+static_assert(std::ranges::range<T6>);
+static_assert(!std::ranges::view<T6>);
+static_assert(std::constructible_from<T6, T6>);
+static_assert(!std::ranges::borrowed_range<T6>);
+
+static_assert(!std::ranges::viewable_range<T6>);
+
+// viewable_range<T> is satisfied for (range=true, view=false, constructible_from=false, borrowed_range=true)
+struct T7 : test_range<cpp20_input_iterator> {
+ T7(T7 const&) = delete;
+};
+static_assert(std::ranges::range<T7&>);
+static_assert(!std::ranges::view<std::remove_cvref_t<T7&>>);
+static_assert(!std::constructible_from<std::remove_cvref_t<T7&>, T7&>);
+static_assert(std::ranges::borrowed_range<T7&>);
+
+static_assert(std::ranges::viewable_range<T7&>);
+
+// A type that satisfies (range=true, view=false, constructible_from=false, borrowed_range=false) can't be formed
+struct T8 : test_range<cpp20_input_iterator> {
+ T8(T8 const&) = delete;
+};
+static_assert(std::ranges::range<T8>);
+static_assert(!std::ranges::view<T8>);
+static_assert(!std::constructible_from<T8, T8>);
+static_assert(!std::ranges::borrowed_range<T8>);
+
+static_assert(!std::ranges::viewable_range<T8>);
+
+// Test with a few degenerate types
+static_assert(!std::ranges::viewable_range<void>);
+static_assert(!std::ranges::viewable_range<int>);
+static_assert(!std::ranges::viewable_range<int (*)(char)>);
+static_assert(!std::ranges::viewable_range<int[]>);
+static_assert(!std::ranges::viewable_range<int[10]>);
+static_assert(!std::ranges::viewable_range<int(&)[]>); // unbounded array is not a range
+static_assert( std::ranges::viewable_range<int(&)[10]>);
static_assert(!stdr::view<std::cmatch>);
static_assert(stdr::sized_range<std::cmatch>);
static_assert(!stdr::borrowed_range<std::cmatch>);
+static_assert(!stdr::viewable_range<std::cmatch>);
static_assert(std::same_as<stdr::iterator_t<std::cmatch const>, std::cmatch::const_iterator>);
static_assert(stdr::common_range<std::cmatch const>);
static_assert(!stdr::view<std::cmatch const>);
static_assert(stdr::sized_range<std::cmatch const>);
static_assert(!stdr::borrowed_range<std::cmatch const>);
+static_assert(!stdr::viewable_range<std::cmatch const>);
static_assert(!stdr::view<std::string>);
static_assert(stdr::sized_range<std::string>);
static_assert(!stdr::borrowed_range<std::string>);
+static_assert(!stdr::viewable_range<std::string>);
static_assert(std::same_as<stdr::iterator_t<std::string const>, std::string::const_iterator>);
static_assert(stdr::common_range<std::string const>);
static_assert(!stdr::view<std::string const>);
static_assert(stdr::sized_range<std::string const>);
static_assert(!stdr::borrowed_range<std::string const>);
+static_assert(!stdr::viewable_range<std::string const>);
static_assert(stdr::view<std::string_view> && stdr::enable_view<std::string_view>);
static_assert(stdr::sized_range<std::string_view>);
static_assert(stdr::borrowed_range<std::string_view>);
+static_assert(stdr::viewable_range<std::string_view>);
static_assert(std::same_as<stdr::iterator_t<std::string_view const>, std::string_view::const_iterator>);
static_assert(stdr::common_range<std::string_view const>);
static_assert(!stdr::view<std::string_view const> && !stdr::enable_view<std::string_view const>);
static_assert(stdr::sized_range<std::string_view const>);
static_assert(stdr::borrowed_range<std::string_view const>);
+static_assert(stdr::viewable_range<std::string_view const>);