Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -2681,8 +2681,21 @@ namespace ranges {

struct view_base {};

template <template <class...> class _Template, class... _Args>
void _Derived_from_specialization_impl(const _Template<_Args...>&);

template <class _Ty, template <class...> class _Template>
concept _Derived_from_specialization_of = requires(const _Ty& _Obj) {
_Derived_from_specialization_impl<_Template>(_Obj);
};

template <class _Derived>
requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
class view_interface;

template <class _Ty>
inline constexpr bool enable_view = derived_from<_Ty, view_base>;
inline constexpr bool enable_view =
derived_from<_Ty, view_base> || _Derived_from_specialization_of<_Ty, view_interface>;

#ifdef __cpp_lib_ranges // TRANSITION, GH-1814
template <class _Ty>
Expand Down Expand Up @@ -3016,7 +3029,7 @@ namespace ranges {
// clang-format off
template <class _Derived>
requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>>
class view_interface : public view_base {
class view_interface {
private:
_NODISCARD constexpr _Derived& _Cast() noexcept {
static_assert(derived_from<_Derived, view_interface>,
Expand Down
29 changes: 28 additions & 1 deletion tests/std/tests/P0896R4_ranges_range_machinery/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1578,6 +1578,7 @@ using immutable_badsized_range = badsized_range<immutable_sized_range>;
template <class T>
constexpr bool ranges::disable_sized_range<badsized_range<T>> = true;

// "strange" in that const-ness affects the iterator type
struct strange_view {
strange_view() = default;
strange_view(strange_view&&) = default;
Expand All @@ -1591,7 +1592,15 @@ struct strange_view {
};

struct strange_view2 : strange_view, ranges::view_base {};
struct strange_view3 : strange_view2 {};
struct strange_view3 : strange_view2 {}; // not truly a view since enable_view<strange_view3> is false (see below)
struct strange_view4 : strange_view, ranges::view_interface<strange_view4> {};
struct strange_view5 : strange_view4, ranges::view_interface<strange_view5> {
// not truly a view since enable_view<strange_view5> is false due to multiple inheritance from view_interface
};

// Verify that specializations of view_interface do not inherit from view_base
STATIC_ASSERT(!std::is_base_of_v<std::ranges::view_base, ranges::view_interface<strange_view4>>);
STATIC_ASSERT(!std::is_base_of_v<std::ranges::view_base, ranges::view_interface<strange_view5>>);

template <>
inline constexpr bool ranges::enable_view<strange_view> = true;
Expand Down Expand Up @@ -1620,6 +1629,7 @@ namespace exhaustive_size_and_view_test {

using I = int*;
using CI = int const*;
using D = std::ptrdiff_t;
using S = std::size_t;
using UC = unsigned char;

Expand Down Expand Up @@ -1682,6 +1692,23 @@ namespace exhaustive_size_and_view_test {
STATIC_ASSERT(test<strange_view3&, false, I, S>());
STATIC_ASSERT(test<strange_view3 const, false, CI, S>());
STATIC_ASSERT(test<strange_view3 const&, false, CI, S>());

STATIC_ASSERT(test<strange_view4, true, I, D>());
STATIC_ASSERT(test<strange_view4&, false, I, D>());
STATIC_ASSERT(test<strange_view4 const, false, CI, D>());
STATIC_ASSERT(test<strange_view4 const&, false, CI, D>());

template <class = void>
constexpr bool strict_test_case() {
if constexpr (!is_permissive) {
STATIC_ASSERT(test<strange_view5, false, I, S>());
}
return true;
}
STATIC_ASSERT(strict_test_case());
STATIC_ASSERT(test<strange_view5&, false, I, S>());
STATIC_ASSERT(test<strange_view5 const, false, CI, S>());
STATIC_ASSERT(test<strange_view5 const&, false, CI, S>());
} // namespace exhaustive_size_and_view_test

// Validate output_range
Expand Down