Thanks to visit codestin.com
Credit goes to github.com

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
13 changes: 12 additions & 1 deletion stl/inc/optional
Original file line number Diff line number Diff line change
Expand Up @@ -952,8 +952,19 @@ _NODISCARD constexpr bool operator>=(const _Ty1& _Left, const optional<_Ty2>& _R
}

#if _HAS_CXX20
#ifdef __EDG__ // TRANSITION, DevCom-10880933
template <class _Ty>
void _Derived_from_optional_impl(const optional<_Ty>&);

template <class _Ty>
concept _Derived_from_optional = requires(const _Ty& __obj) { _STD _Derived_from_optional_impl(__obj); };
#else // ^^^ workaround / no workaround vvv
template <class _Ty>
concept _Derived_from_optional = requires(const _Ty& __obj) { []<class _Uty>(const optional<_Uty>&) {}(__obj); };
#endif // ^^^ no workaround ^^^

_EXPORT_STD template <class _Ty1, class _Ty2>
requires (!_Derived_from_specialization_of<_Ty2, optional>) && three_way_comparable_with<_Ty1, _Ty2>
requires (!_Derived_from_optional<_Ty2>) && three_way_comparable_with<_Ty1, _Ty2>
_NODISCARD constexpr compare_three_way_result_t<_Ty1, _Ty2> operator<=>(const optional<_Ty1>& _Left, const _Ty2& _Right)
noexcept(noexcept(*_Left <=> _Right)) /* strengthened */ {
if (_Left) {
Expand Down
22 changes: 8 additions & 14 deletions stl/inc/xutility
Original file line number Diff line number Diff line change
Expand Up @@ -824,14 +824,6 @@ using _Algorithm_int_t = conditional_t<is_integral_v<_Ty>, _Ty, ptrdiff_t>;
template <class _Ty>
concept _Destructible_object = is_object_v<_Ty> && destructible<_Ty>;

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) {
_STD _Derived_from_specialization_impl<_Template>(_Obj); // qualified: avoid ADL, handle incomplete types
};

namespace ranges {
namespace _Iter_move {
#if defined(__clang__) || defined(__EDG__) // TRANSITION, VSO-1681199
Expand Down Expand Up @@ -3424,17 +3416,19 @@ namespace ranges {

_EXPORT_STD struct view_base {};

template <class _Ty, template <class...> class _Template>
concept _Strictly_derived_from_specialization_of =
is_object_v<_Ty> && _Derived_from_specialization_of<_Ty, _Template>;

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

template <class _Ty, class _Uty>
requires (!is_same_v<_Ty, view_interface<_Uty>>)
void _Strictly_derived_from_view_interface_impl(view_interface<_Uty>*);

_EXPORT_STD template <class _Ty>
constexpr bool enable_view =
derived_from<_Ty, view_base> || _Strictly_derived_from_specialization_of<_Ty, view_interface>;
constexpr bool enable_view = derived_from<_Ty, view_base> || requires {
_RANGES _Strictly_derived_from_view_interface_impl<remove_cv_t<_Ty>>(
static_cast<remove_cv_t<_Ty>*>(nullptr)); // qualified: avoid ADL, handle incomplete types
};

_EXPORT_STD template <class _Ty>
concept view = range<_Ty> && movable<_Ty> && enable_view<_Ty>;
Expand Down
143 changes: 143 additions & 0 deletions tests/std/tests/P0896R4_ranges_range_machinery/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1753,6 +1753,25 @@ static_assert(!ranges::enable_view<const strange_view4&>);
static_assert(!ranges::enable_view<strange_view4&&>);
static_assert(!ranges::enable_view<const strange_view4&&>);

// Verify that enable_view<view_interface<T>> is false, i.e., strict derivation is required
static_assert(!ranges::enable_view<ranges::view_interface<strange_view4>>);
static_assert(!ranges::enable_view<ranges::view_interface<strange_view5>>);

// Verify that enable_view ignores cv-qualification by default
template <class T>
void test_enable_view_cv() { // COMPILE-ONLY
static_assert(ranges::enable_view<const T> == ranges::enable_view<T>);
static_assert(ranges::enable_view<volatile T> == ranges::enable_view<T>);
static_assert(ranges::enable_view<const volatile T> == ranges::enable_view<T>);
}

void test_enable_view_cv_all() { // COMPILE-ONLY
test_enable_view_cv<strange_view4>();
test_enable_view_cv<strange_view5>();
test_enable_view_cv<ranges::view_interface<strange_view4>>();
test_enable_view_cv<ranges::view_interface<strange_view5>>();
}

// Verify that the derived-from-view_interface mechanism can handle uses of incomplete types whenever possible
struct incomplet;

Expand All @@ -1768,6 +1787,80 @@ inline constexpr bool ranges::enable_view<strange_view> = true;
template <>
inline constexpr bool ranges::enable_view<strange_view3> = false;

// Test types that satisfy `view` only when being cv-qualified.

struct view_when_const1 : ranges::view_base {
view_when_const1(const view_when_const1&&);
const view_when_const1& operator=(const view_when_const1&&) const;

friend void swap(const view_when_const1&, const view_when_const1&);

int* begin() const;
int* end() const;
};

struct view_when_const2 : ranges::view_interface<view_when_const2> {
view_when_const2(const view_when_const2&&);
const view_when_const2& operator=(const view_when_const2&&) const;

friend void swap(const view_when_const2&, const view_when_const2&);

int* begin() const;
int* end() const;

// avoid checking ranges::view_interface<view_when_const2>::size()
void size() = delete;
void size() const = delete;
};

struct view_when_volatile1 : ranges::view_base {
view_when_volatile1(volatile view_when_volatile1&&);
volatile view_when_volatile1& operator=(volatile view_when_volatile1&&) volatile;

friend void swap(volatile view_when_volatile1&, volatile view_when_volatile1&);

int* begin() volatile;
int* end() volatile;
};

struct view_when_volatile2 : ranges::view_interface<view_when_volatile2> {
view_when_volatile2(volatile view_when_volatile2&&);
volatile view_when_volatile2& operator=(volatile view_when_volatile2&&) volatile;

friend void swap(volatile view_when_volatile2&, volatile view_when_volatile2&);

int* begin() volatile;
int* end() volatile;

// avoid checking ranges::view_interface<view_when_volatile2>::size()
void size() = delete;
void size() const = delete;
};

struct view_when_const_volatile1 : ranges::view_base {
view_when_const_volatile1(const volatile view_when_const_volatile1&&);
const volatile view_when_const_volatile1& operator=(const volatile view_when_const_volatile1&&) const volatile;

friend void swap(const volatile view_when_const_volatile1&, const volatile view_when_const_volatile1&);

int* begin() const volatile;
int* end() const volatile;
};

struct view_when_const_volatile2 : ranges::view_interface<view_when_const_volatile2> {
view_when_const_volatile2(const volatile view_when_const_volatile2&&);
const volatile view_when_const_volatile2& operator=(const volatile view_when_const_volatile2&&) const volatile;

friend void swap(const volatile view_when_const_volatile2&, const volatile view_when_const_volatile2&);

int* begin() const volatile;
int* end() const volatile;

// avoid checking ranges::view_interface<view_when_const_volatile2>::size()
void size() = delete;
void size() const = delete;
};

namespace exhaustive_size_and_view_test {
template <class Rng, bool IsView = false, class Iterator = invalid_type, class Size = invalid_type>
constexpr bool test() {
Expand Down Expand Up @@ -1869,6 +1962,56 @@ namespace exhaustive_size_and_view_test {
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>());

static_assert(test<view_when_const1, false, I, S>());
static_assert(test<view_when_const1 const, true, I, S>());
static_assert(test<view_when_const1&, false, I, S>());
static_assert(test<view_when_const1 const&, false, I, S>());

static_assert(test<view_when_const2, false, I, S>());
static_assert(test<view_when_const2 const, true, I, S>());
static_assert(test<view_when_const2&, false, I, S>());
static_assert(test<view_when_const2 const&, false, I, S>());

static_assert(test<view_when_volatile1, false, I, S>());
static_assert(test<view_when_volatile1 const, false>());
static_assert(test<view_when_volatile1&, false, I, S>());
static_assert(test<view_when_volatile1 const&, false>());

static_assert(test<view_when_volatile2, false, I, S>());
static_assert(test<view_when_volatile2 const, false>());
static_assert(test<view_when_volatile2&, false, I, S>());
static_assert(test<view_when_volatile2 const&, false>());

static_assert(test<view_when_volatile1 volatile, true, I, S>());
static_assert(test<view_when_volatile1 const volatile, false>());
static_assert(test<view_when_volatile1 volatile&, false, I, S>());
static_assert(test<view_when_volatile1 const volatile&, false>());

static_assert(test<view_when_volatile2 volatile, true, I, S>());
static_assert(test<view_when_volatile2 const volatile, false>());
static_assert(test<view_when_volatile2 volatile&, false, I, S>());
static_assert(test<view_when_volatile2 const volatile&, false>());

static_assert(test<view_when_const_volatile1, false, I, S>());
static_assert(test<view_when_const_volatile1 const, false, I, S>());
static_assert(test<view_when_const_volatile1&, false, I, S>());
static_assert(test<view_when_const_volatile1 const&, false, I, S>());

static_assert(test<view_when_const_volatile2, false, I, S>());
static_assert(test<view_when_const_volatile2 const, false, I, S>());
static_assert(test<view_when_const_volatile2&, false, I, S>());
static_assert(test<view_when_const_volatile2 const&, false, I, S>());

static_assert(test<view_when_const_volatile1 volatile, false, I, S>());
static_assert(test<view_when_const_volatile1 const volatile, true, I, S>());
static_assert(test<view_when_const_volatile1 volatile&, false, I, S>());
static_assert(test<view_when_const_volatile1 const volatile&, false, I, S>());

static_assert(test<view_when_const_volatile2 volatile, false, I, S>());
static_assert(test<view_when_const_volatile2 const volatile, true, I, S>());
static_assert(test<view_when_const_volatile2 volatile&, false, I, S>());
static_assert(test<view_when_const_volatile2 const volatile&, false, I, S>());
} // namespace exhaustive_size_and_view_test

// Validate output_range
Expand Down