From 001654a3559e0c089a59233bfb124abb997742aa Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 14 Feb 2024 01:41:04 +0800 Subject: [PATCH 1/3] Make views ADL-proof By qualifying `_Fake_copy_init`, `_Adl_verify_range`, and `_As_lvalue`. --- stl/inc/ranges | 87 ++-- .../test.compile.pass.cpp | 381 ++++++++++++++++++ 2 files changed, 425 insertions(+), 43 deletions(-) diff --git a/stl/inc/ranges b/stl/inc/ranges index 5e820d13bf9..7e08de8f4da 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2217,9 +2217,9 @@ namespace ranges { is_nothrow_move_constructible_v>) // strengthened : _Current(_STD move(_Current_)), _Parent{_STD addressof(_Parent_)} { #if _ITERATOR_DEBUG_LEVEL != 0 - _Adl_verify_range(_Current, _RANGES end(_Parent_._Range)); + _STD _Adl_verify_range(_Current, _RANGES end(_Parent_._Range)); if constexpr (forward_range<_Vw>) { - _Adl_verify_range(_RANGES begin(_Parent_._Range), _Current); + _STD _Adl_verify_range(_RANGES begin(_Parent_._Range), _Current); } #endif // _ITERATOR_DEBUG_LEVEL != 0 } @@ -2324,7 +2324,7 @@ namespace ranges { } _NODISCARD constexpr bool _Equal(const sentinel_t<_Vw>& _Last) const - noexcept(noexcept(_Fake_copy_init(_Current == _Last))) { + noexcept(noexcept(_STD _Fake_copy_init(_Current == _Last))) { return _Current == _Last; } }; @@ -2494,9 +2494,9 @@ namespace ranges { is_nothrow_move_constructible_v>) // strengthened : _Current{_STD move(_Current_)}, _Parent{_STD addressof(_Parent_)} { #if _ITERATOR_DEBUG_LEVEL != 0 - _Adl_verify_range(_Current, _RANGES end(_Parent_._Range)); + _STD _Adl_verify_range(_Current, _RANGES end(_Parent_._Range)); if constexpr (forward_range<_Base>) { - _Adl_verify_range(_RANGES begin(_Parent_._Range), _Current); + _STD _Adl_verify_range(_RANGES begin(_Parent_._Range), _Current); } #endif // _ITERATOR_DEBUG_LEVEL != 0 } @@ -3752,8 +3752,8 @@ namespace ranges { requires forward_range<_Base> : _Mybase{_STD move(_Outer_)}, _Parent{_STD addressof(_Parent_)} { #if _ITERATOR_DEBUG_LEVEL != 0 - _Adl_verify_range(this->_Outer, _RANGES end(_Parent_._Range)); - _Adl_verify_range(_RANGES begin(_Parent_._Range), this->_Outer); + _STD _Adl_verify_range(this->_Outer, _RANGES end(_Parent_._Range)); + _STD _Adl_verify_range(_RANGES begin(_Parent_._Range), this->_Outer); #endif // _ITERATOR_DEBUG_LEVEL != 0 _Satisfy(); } @@ -3809,7 +3809,7 @@ namespace ranges { _STL_VERIFY(_Get_outer() != _RANGES end(_Parent->_Range), "cannot dereference join_view end iterator"); sentinel_t<_InnerRng<_Const>> _Last; if constexpr (_Deref_is_glvalue) { - _Last = _RANGES end(_As_lvalue(*_Get_outer())); + _Last = _RANGES end(_RANGES _As_lvalue(*_Get_outer())); } else { _Last = _RANGES end((*_Parent->_Inner)._Val); } @@ -3858,7 +3858,7 @@ namespace ranges { constexpr _Iterator& operator++() { auto& _Outer = _Get_outer(); if constexpr (_Deref_is_glvalue) { - if (++*_Inner == _RANGES end(_As_lvalue(*_Outer))) { + if (++*_Inner == _RANGES end(_RANGES _As_lvalue(*_Outer))) { ++_Outer; _Satisfy(); } @@ -3888,11 +3888,11 @@ namespace ranges { auto& _Outer = _Get_outer(); if (_Outer == _RANGES end(_Parent->_Range)) { --_Outer; - _Inner = _RANGES end(_As_lvalue(*_Outer)); + _Inner = _RANGES end(_RANGES _As_lvalue(*_Outer)); } - while (*_Inner == _RANGES begin(_As_lvalue(*_Outer))) { + while (*_Inner == _RANGES begin(_RANGES _As_lvalue(*_Outer))) { --_Outer; - *_Inner = _RANGES end(_As_lvalue(*_Outer)); + *_Inner = _RANGES end(_RANGES _As_lvalue(*_Outer)); } --*_Inner; return *this; @@ -3954,7 +3954,7 @@ namespace ranges { template requires sentinel_for, _Maybe_const_iter<_OtherConst>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const - noexcept(noexcept(_Fake_copy_init(_It._Get_outer() == _Last))) { + noexcept(noexcept(_STD _Fake_copy_init(_It._Get_outer() == _Last))) { return _It._Get_outer() == _Last; } @@ -4221,7 +4221,7 @@ namespace ranges { _NODISCARD constexpr auto& _Update_inner() { if constexpr (_Deref_is_glvalue) { - return _As_lvalue(*_Get_outer()); + return _RANGES _As_lvalue(*_Get_outer()); } else { return _Parent->_Inner._Emplace(_Construct_tag{}, _Get_outer())._Val; } @@ -4229,7 +4229,7 @@ namespace ranges { _NODISCARD constexpr auto& _Get_inner() noexcept { if constexpr (_Deref_is_glvalue) { - return _As_lvalue(*_Get_outer()); + return _RANGES _As_lvalue(*_Get_outer()); } else { return (*_Parent->_Inner)._Val; } @@ -4467,7 +4467,7 @@ namespace ranges { template _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const - noexcept(noexcept(_Fake_copy_init(_It._Get_outer() == _Last))) { + noexcept(noexcept(_STD _Fake_copy_init(_It._Get_outer() == _Last))) { _STL_INTERNAL_STATIC_ASSERT( sentinel_for, iterator_t<_Maybe_const<_OtherConst, _Vw>>>); return _It._Get_outer() == _Last; @@ -4693,7 +4693,7 @@ namespace ranges { } _NODISCARD constexpr bool _At_end() const - noexcept(noexcept(_Fake_copy_init(_Get_current() == _RANGES end(_Parent->_Range)))) { + noexcept(noexcept(_STD _Fake_copy_init(_Get_current() == _RANGES end(_Parent->_Range)))) { return _Get_current() == _RANGES end(_Parent->_Range); } @@ -5113,7 +5113,7 @@ namespace ranges { /* [[no_unique_address]] */ sentinel_t<_Vw> _Last{}; _NODISCARD constexpr bool _Equal(const _Iterator& _It) const - noexcept(noexcept(_Fake_copy_init(_It._Current == _Last))) { + noexcept(noexcept(_STD _Fake_copy_init(_It._Current == _Last))) { return !_It._Trailing_empty && _It._Current == _Last; } @@ -6306,7 +6306,7 @@ namespace ranges { template requires sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const - noexcept(noexcept(_Fake_copy_init(_It._Current == _End))) { + noexcept(noexcept(_STD _Fake_copy_init(_It._Current == _End))) { return _It._Current == _End; } @@ -6850,38 +6850,38 @@ namespace ranges { } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept( - noexcept(_Fake_copy_init(_Left._Current == _Left._End))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_Left._Current == _Left._End))) /* strengthened */ { return _Left._Current == _Left._End; } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current < _Right._Current))) /* strengthened */ + noexcept(_STD _Fake_copy_init(_Left._Current < _Right._Current))) /* strengthened */ requires random_access_range<_Base> { return _Left._Current < _Right._Current; } _NODISCARD_FRIEND constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Right._Current < _Left._Current))) /* strengthened */ + noexcept(_STD _Fake_copy_init(_Right._Current < _Left._Current))) /* strengthened */ requires random_access_range<_Base> { return _Right._Current < _Left._Current; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(!(_Right._Current < _Left._Current)))) /* strengthened */ + noexcept(_STD _Fake_copy_init(!(_Right._Current < _Left._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Right._Current < _Left._Current); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(!(_Left._Current < _Right._Current)))) /* strengthened */ + noexcept(_STD _Fake_copy_init(!(_Left._Current < _Right._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Left._Current < _Right._Current); @@ -7209,7 +7209,7 @@ namespace ranges { } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { if constexpr (_Slide_caches_first<_Base>) { return _Left._Last_element == _Right._Last_element; } else { @@ -7218,28 +7218,28 @@ namespace ranges { } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current < _Right._Current))) /* strengthened */ + noexcept(_STD _Fake_copy_init(_Left._Current < _Right._Current))) /* strengthened */ requires random_access_range<_Base> { return _Left._Current < _Right._Current; } _NODISCARD_FRIEND constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Right._Current < _Left._Current))) /* strengthened */ + noexcept(_STD _Fake_copy_init(_Right._Current < _Left._Current))) /* strengthened */ requires random_access_range<_Base> { return _Right._Current < _Left._Current; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(!(_Right._Current < _Left._Current)))) /* strengthened */ + noexcept(_STD _Fake_copy_init(!(_Right._Current < _Left._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Right._Current < _Left._Current); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(!(_Left._Current < _Right._Current)))) /* strengthened */ + noexcept(_STD _Fake_copy_init(!(_Left._Current < _Right._Current)))) /* strengthened */ requires random_access_range<_Base> { return !(_Left._Current < _Right._Current); @@ -7304,8 +7304,8 @@ namespace ranges { _Sentinel() = default; _NODISCARD_FRIEND constexpr bool - operator==(const _Iterator& _Left, const _Sentinel& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Get_last_element() == _Right._Last))) /* strengthened */ { + operator==(const _Iterator& _Left, const _Sentinel& _Right) noexcept(noexcept( + _STD _Fake_copy_init(_Left._Get_last_element() == _Right._Last))) /* strengthened */ { return _Left._Get_last_element() == _Right._Last; } @@ -7557,12 +7557,12 @@ namespace ranges { } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_Left._Current == _Right._Current))) /* strengthened */ { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept( - noexcept(_Fake_copy_init(_Left._Current == _Left._Next))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_Left._Current == _Left._Next))) /* strengthened */ { return _Left._Current == _Left._Next; } }; @@ -7824,40 +7824,40 @@ namespace ranges { } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _It, default_sentinel_t) noexcept( - noexcept(_Fake_copy_init(_It._Current == _It._End))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_It._Current == _It._End))) /* strengthened */ { return _It._Current == _It._End; } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current == _Right._Current))) // strengthened + noexcept(_STD _Fake_copy_init(_Left._Current == _Right._Current))) // strengthened requires equality_comparable<_Base_iterator> { return _Left._Current == _Right._Current; } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current < _Right._Current))) // strengthened + noexcept(_STD _Fake_copy_init(_Left._Current < _Right._Current))) // strengthened requires random_access_range<_Base> { return _Left._Current < _Right._Current; } _NODISCARD_FRIEND constexpr bool operator>(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Right._Current < _Left._Current))) // strengthened + noexcept(_STD _Fake_copy_init(_Right._Current < _Left._Current))) // strengthened requires random_access_range<_Base> { return _Right._Current < _Left._Current; } _NODISCARD_FRIEND constexpr bool operator<=(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(!(_Right._Current < _Left._Current)))) // strengthened + noexcept(_STD _Fake_copy_init(!(_Right._Current < _Left._Current)))) // strengthened requires random_access_range<_Base> { return !(_Right._Current < _Left._Current); } _NODISCARD_FRIEND constexpr bool operator>=(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(!(_Left._Current < _Right._Current)))) // strengthened + noexcept(_STD _Fake_copy_init(!(_Left._Current < _Right._Current)))) // strengthened requires random_access_range<_Base> { return !(_Left._Current < _Right._Current); @@ -9126,12 +9126,13 @@ namespace ranges { } _NODISCARD_FRIEND constexpr bool operator==(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current.back() == _Right._Current.back()))) /* strengthened */ { + noexcept(_STD _Fake_copy_init(_Left._Current.back() == _Right._Current.back()))) // strengthened + { return _Left._Current.back() == _Right._Current.back(); } _NODISCARD_FRIEND constexpr bool operator<(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_Fake_copy_init(_Left._Current.back() < _Right._Current.back()))) // strengthened + noexcept(_STD _Fake_copy_init(_Left._Current.back() < _Right._Current.back()))) // strengthened requires random_access_range<_Base> { return _Left._Current.back() < _Right._Current.back(); @@ -9236,7 +9237,7 @@ namespace ranges { template requires sentinel_for<_Base_sentinel, iterator_t<_Maybe_const<_OtherConst, _Vw>>> _NODISCARD constexpr bool _Equal(const _Iterator<_OtherConst>& _It) const - noexcept(noexcept(_Fake_copy_init(_It._Current.back() == _End))) { + noexcept(noexcept(_STD _Fake_copy_init(_It._Current.back() == _End))) { return _It._Current.back() == _End; } diff --git a/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp b/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp index 70c5665ca46..063283a47da 100644 --- a/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp +++ b/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp @@ -248,6 +248,387 @@ void test_adl_proof_optional_comparison() { } #endif // _HAS_CXX17 +#if _HAS_CXX20 +struct validating_view_for_verification { + constexpr holder** begin() const noexcept { + return begin_; + } + + constexpr holder** end() const noexcept { + return end_; + } + + holder** begin_; + holder** end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template +struct tagged_ints_view { + constexpr int* begin() const noexcept { + return begin_; + } + + constexpr int* end() const noexcept { + return end_; + } + + int* begin_; + int* end_; +}; + +template +inline constexpr bool ranges::enable_view> = true; + +template +inline constexpr bool ranges::enable_borrowed_range> = true; + +struct validating_view_to_join_for_verification { + constexpr const tagged_ints_view>* begin() const noexcept { + return begin_; + } + + constexpr const tagged_ints_view>* end() const noexcept { + return end_; + } + + const tagged_ints_view>* begin_; + const tagged_ints_view>* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +void test_views_verification() { + constexpr auto simple_truth = [](const auto&) { return true; }; + + holder* varr[1]{}; + const validating_view_for_verification validating_view_val{varr, varr + 1}; + + for (auto&& _ [[maybe_unused]] : validating_view_val | views::filter(simple_truth)) + ; + + for (auto&& _ [[maybe_unused]] : validating_view_val | views::transform(simple_truth)) + ; + + int iarr[1]{}; + const tagged_ints_view> inner_arr[1]{{iarr, iarr + 1}}; + const validating_view_to_join_for_verification view_to_join{inner_arr, inner_arr + 1}; + + for (auto&& _ [[maybe_unused]] : view_to_join | views::join) + ; + + for (auto&& _ [[maybe_unused]] : view_to_join | views::join | views::reverse) + ; + +#if _HAS_CXX23 + const tagged_ints_view simple_pattern{iarr, iarr + 1}; + + for (auto&& _ [[maybe_unused]] : view_to_join | views::join_with(simple_pattern)) + ; +#endif // _HAS_CXX23 +} + +struct validating_common_view { + using iterator = validating_iterator_provider::iterator; + + constexpr iterator begin() const noexcept { + return {begin_}; + } + + constexpr iterator end() const noexcept { + return {end_}; + } + + int* begin_; + int* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template +struct noncommon_sentinel_for { + using pointer = iterator_traits::pointer; + + pointer p_end_; + + friend constexpr holder* const* operator==(const I i, const noncommon_sentinel_for s) noexcept { + return to_address(i) == s.p_end_ ? placeholder_addr : nullptr; + } + friend constexpr holder* const* operator==(const noncommon_sentinel_for s, const I i) noexcept { + return to_address(i) == s.p_end_ ? placeholder_addr : nullptr; + } + friend constexpr holder* const* operator!=(const I i, const noncommon_sentinel_for s) noexcept { + return to_address(i) == s.p_end_ ? nullptr : placeholder_addr; + } + friend constexpr holder* const* operator!=(const noncommon_sentinel_for s, const I i) noexcept { + return to_address(i) == s.p_end_ ? nullptr : placeholder_addr; + } +}; + +struct validating_noncommon_view { + using iterator = validating_iterator_provider::iterator; + + constexpr iterator begin() const noexcept { + return {begin_}; + } + + constexpr noncommon_sentinel_for end() const noexcept { + return {end_}; + } + + int* begin_; + int* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + + +struct validating_noncommon_to_join_view { + using iterator = const validating_noncommon_view*; + + constexpr iterator begin() const noexcept { + return begin_; + } + + constexpr noncommon_sentinel_for end() const noexcept { + return {end_}; + } + + const validating_noncommon_view* begin_; + const validating_noncommon_view* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +struct negation_validating_iterator { + struct boolean_testable_result { + constexpr operator bool() const noexcept { + return val_; + } + + constexpr holder* const* operator!() const noexcept { + return val_ ? placeholder_addr : nullptr; + } + bool val_; + }; + + using value_type = int; + using reference = int&; + using pointer = int*; + using difference_type = ptrdiff_t; + using iterator_category = random_access_iterator_tag; + using iterator_concept = contiguous_iterator_tag; + + constexpr int& operator*() const noexcept { + return *ptr_; + } + + constexpr int* operator->() const noexcept { + return ptr_; + } + + constexpr negation_validating_iterator& operator++() noexcept { + ++ptr_; + return *this; + } + constexpr negation_validating_iterator operator++(int) noexcept { + auto old = *this; + ++ptr_; + return old; + } + + constexpr negation_validating_iterator& operator--() noexcept { + --ptr_; + return *this; + } + constexpr negation_validating_iterator operator--(int) noexcept { + auto old = *this; + --ptr_; + return old; + } + + constexpr negation_validating_iterator& operator+=(const ptrdiff_t n) noexcept { + ptr_ += n; + return *this; + } + + constexpr negation_validating_iterator& operator-=(const ptrdiff_t n) noexcept { + ptr_ -= n; + return *this; + } + + constexpr int& operator[](const ptrdiff_t n) const noexcept { + return ptr_[n]; + } + + friend constexpr negation_validating_iterator operator+( + const negation_validating_iterator i, const ptrdiff_t n) noexcept { + return {i.ptr_ + n}; + } + friend constexpr negation_validating_iterator operator+( + const ptrdiff_t n, const negation_validating_iterator i) noexcept { + return {i.ptr_ + n}; + } + friend constexpr negation_validating_iterator operator-( + const negation_validating_iterator i, const ptrdiff_t n) noexcept { + return {i.ptr_ - n}; + } + friend constexpr ptrdiff_t operator-( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return i.ptr_ - j.ptr_; + } + + friend constexpr boolean_testable_result operator==( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ == j.ptr_}; + } + + friend constexpr boolean_testable_result operator!=( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ != j.ptr_}; + } + + friend constexpr boolean_testable_result operator<( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ < j.ptr_}; + } + + friend constexpr boolean_testable_result operator>( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ > j.ptr_}; + } + + friend constexpr boolean_testable_result operator<=( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ <= j.ptr_}; + } + + friend constexpr boolean_testable_result operator>=( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ <= j.ptr_}; + } + + int* ptr_; +}; + +struct validating_negation_view { + constexpr negation_validating_iterator begin() const noexcept { + return {begin_}; + } + + constexpr negation_validating_iterator end() const noexcept { + return {end_}; + } + + int* begin_; + int* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template +void test_adl_proof_random_access_views_comparison(V&& v) { + auto i = v.begin(); + auto j = v.end(); + + (void) (i == j); + (void) (i != j); + (void) (i < j); + (void) (i > j); + (void) (i <= j); + (void) (i >= j); +} + +template +void test_adl_proof_basic_views_comparison(V&& v) { + auto it = v.begin(); + auto se = v.end(); + + (void) (it == se); + (void) (it != se); +} + +void test_adl_proof_views_comparison() { + constexpr auto simple_truth = [](const auto&) { return true; }; + + int iarr[1]{}; + const validating_common_view validating_common_view_val{iarr, iarr + 1}; + const validating_noncommon_view validating_noncommon_view_val{iarr, iarr + 1}; + const validating_negation_view validating_negation_view_val{iarr, iarr + 1}; + const validating_noncommon_to_join_view validating_view_to_join{ + &validating_noncommon_view_val, &validating_noncommon_view_val + 1}; + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::filter(simple_truth)); + test_adl_proof_basic_views_comparison(validating_negation_view_val | views::filter(simple_truth)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::filter(simple_truth)); + + test_adl_proof_basic_views_comparison(validating_view_to_join | views::join); + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::split(validating_common_view_val)); + test_adl_proof_basic_views_comparison(validating_negation_view_val | views::split(validating_negation_view_val)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::split(validating_noncommon_view_val)); + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::lazy_split(validating_common_view_val)); + test_adl_proof_basic_views_comparison( + validating_negation_view_val | views::lazy_split(validating_negation_view_val)); + test_adl_proof_basic_views_comparison( + validating_noncommon_view_val | views::lazy_split(validating_noncommon_view_val)); + +#if _HAS_CXX23 + test_adl_proof_basic_views_comparison(validating_view_to_join | views::join_with(validating_noncommon_view_val)); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::enumerate); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::enumerate); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::enumerate); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::chunk(1)); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::chunk(1)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::chunk(1)); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::slide(1)); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::slide(1)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::slide(1)); + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::chunk_by(ranges::equal_to{})); + test_adl_proof_basic_views_comparison(validating_negation_view_val | views::chunk_by(ranges::equal_to{})); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::chunk_by(ranges::equal_to{})); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::stride(1)); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::stride(1)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::stride(1)); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::adjacent<1>); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::adjacent<1>); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::adjacent<1>); +#endif // _HAS_CXX23 +} +#endif // _HAS_CXX20 + #if _HAS_CXX23 void test_adl_proof_expected_comparison() { expected ex; From 2865e0425f4b25d5db773e4194421fc6a5afb3b3 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Wed, 14 Feb 2024 12:01:50 +0800 Subject: [PATCH 2/3] Separate tests --- tests/std/test.lst | 1 + .../test.compile.pass.cpp | 381 ------------- .../tests/GH_000140_adl_proof_views/env.lst | 4 + .../test.compile.pass.cpp | 525 ++++++++++++++++++ 4 files changed, 530 insertions(+), 381 deletions(-) create mode 100644 tests/std/tests/GH_000140_adl_proof_views/env.lst create mode 100644 tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 23a3ac90014..5a7f22df0b8 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -156,6 +156,7 @@ tests\Dev11_1150223_shared_mutex tests\Dev11_1158803_regex_thread_safety tests\Dev11_1180290_filesystem_error_code tests\GH_000140_adl_proof_comparison +tests\GH_000140_adl_proof_views tests\GH_000177_forbidden_aliasing tests\GH_000178_uniform_int tests\GH_000342_filebuf_close diff --git a/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp b/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp index 063283a47da..70c5665ca46 100644 --- a/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp +++ b/tests/std/tests/GH_000140_adl_proof_comparison/test.compile.pass.cpp @@ -248,387 +248,6 @@ void test_adl_proof_optional_comparison() { } #endif // _HAS_CXX17 -#if _HAS_CXX20 -struct validating_view_for_verification { - constexpr holder** begin() const noexcept { - return begin_; - } - - constexpr holder** end() const noexcept { - return end_; - } - - holder** begin_; - holder** end_; -}; - -template <> -inline constexpr bool ranges::enable_view = true; - -template <> -inline constexpr bool ranges::enable_borrowed_range = true; - -template -struct tagged_ints_view { - constexpr int* begin() const noexcept { - return begin_; - } - - constexpr int* end() const noexcept { - return end_; - } - - int* begin_; - int* end_; -}; - -template -inline constexpr bool ranges::enable_view> = true; - -template -inline constexpr bool ranges::enable_borrowed_range> = true; - -struct validating_view_to_join_for_verification { - constexpr const tagged_ints_view>* begin() const noexcept { - return begin_; - } - - constexpr const tagged_ints_view>* end() const noexcept { - return end_; - } - - const tagged_ints_view>* begin_; - const tagged_ints_view>* end_; -}; - -template <> -inline constexpr bool ranges::enable_view = true; - -template <> -inline constexpr bool ranges::enable_borrowed_range = true; - -void test_views_verification() { - constexpr auto simple_truth = [](const auto&) { return true; }; - - holder* varr[1]{}; - const validating_view_for_verification validating_view_val{varr, varr + 1}; - - for (auto&& _ [[maybe_unused]] : validating_view_val | views::filter(simple_truth)) - ; - - for (auto&& _ [[maybe_unused]] : validating_view_val | views::transform(simple_truth)) - ; - - int iarr[1]{}; - const tagged_ints_view> inner_arr[1]{{iarr, iarr + 1}}; - const validating_view_to_join_for_verification view_to_join{inner_arr, inner_arr + 1}; - - for (auto&& _ [[maybe_unused]] : view_to_join | views::join) - ; - - for (auto&& _ [[maybe_unused]] : view_to_join | views::join | views::reverse) - ; - -#if _HAS_CXX23 - const tagged_ints_view simple_pattern{iarr, iarr + 1}; - - for (auto&& _ [[maybe_unused]] : view_to_join | views::join_with(simple_pattern)) - ; -#endif // _HAS_CXX23 -} - -struct validating_common_view { - using iterator = validating_iterator_provider::iterator; - - constexpr iterator begin() const noexcept { - return {begin_}; - } - - constexpr iterator end() const noexcept { - return {end_}; - } - - int* begin_; - int* end_; -}; - -template <> -inline constexpr bool ranges::enable_view = true; - -template <> -inline constexpr bool ranges::enable_borrowed_range = true; - -template -struct noncommon_sentinel_for { - using pointer = iterator_traits::pointer; - - pointer p_end_; - - friend constexpr holder* const* operator==(const I i, const noncommon_sentinel_for s) noexcept { - return to_address(i) == s.p_end_ ? placeholder_addr : nullptr; - } - friend constexpr holder* const* operator==(const noncommon_sentinel_for s, const I i) noexcept { - return to_address(i) == s.p_end_ ? placeholder_addr : nullptr; - } - friend constexpr holder* const* operator!=(const I i, const noncommon_sentinel_for s) noexcept { - return to_address(i) == s.p_end_ ? nullptr : placeholder_addr; - } - friend constexpr holder* const* operator!=(const noncommon_sentinel_for s, const I i) noexcept { - return to_address(i) == s.p_end_ ? nullptr : placeholder_addr; - } -}; - -struct validating_noncommon_view { - using iterator = validating_iterator_provider::iterator; - - constexpr iterator begin() const noexcept { - return {begin_}; - } - - constexpr noncommon_sentinel_for end() const noexcept { - return {end_}; - } - - int* begin_; - int* end_; -}; - -template <> -inline constexpr bool ranges::enable_view = true; - -template <> -inline constexpr bool ranges::enable_borrowed_range = true; - - -struct validating_noncommon_to_join_view { - using iterator = const validating_noncommon_view*; - - constexpr iterator begin() const noexcept { - return begin_; - } - - constexpr noncommon_sentinel_for end() const noexcept { - return {end_}; - } - - const validating_noncommon_view* begin_; - const validating_noncommon_view* end_; -}; - -template <> -inline constexpr bool ranges::enable_view = true; - -template <> -inline constexpr bool ranges::enable_borrowed_range = true; - -struct negation_validating_iterator { - struct boolean_testable_result { - constexpr operator bool() const noexcept { - return val_; - } - - constexpr holder* const* operator!() const noexcept { - return val_ ? placeholder_addr : nullptr; - } - bool val_; - }; - - using value_type = int; - using reference = int&; - using pointer = int*; - using difference_type = ptrdiff_t; - using iterator_category = random_access_iterator_tag; - using iterator_concept = contiguous_iterator_tag; - - constexpr int& operator*() const noexcept { - return *ptr_; - } - - constexpr int* operator->() const noexcept { - return ptr_; - } - - constexpr negation_validating_iterator& operator++() noexcept { - ++ptr_; - return *this; - } - constexpr negation_validating_iterator operator++(int) noexcept { - auto old = *this; - ++ptr_; - return old; - } - - constexpr negation_validating_iterator& operator--() noexcept { - --ptr_; - return *this; - } - constexpr negation_validating_iterator operator--(int) noexcept { - auto old = *this; - --ptr_; - return old; - } - - constexpr negation_validating_iterator& operator+=(const ptrdiff_t n) noexcept { - ptr_ += n; - return *this; - } - - constexpr negation_validating_iterator& operator-=(const ptrdiff_t n) noexcept { - ptr_ -= n; - return *this; - } - - constexpr int& operator[](const ptrdiff_t n) const noexcept { - return ptr_[n]; - } - - friend constexpr negation_validating_iterator operator+( - const negation_validating_iterator i, const ptrdiff_t n) noexcept { - return {i.ptr_ + n}; - } - friend constexpr negation_validating_iterator operator+( - const ptrdiff_t n, const negation_validating_iterator i) noexcept { - return {i.ptr_ + n}; - } - friend constexpr negation_validating_iterator operator-( - const negation_validating_iterator i, const ptrdiff_t n) noexcept { - return {i.ptr_ - n}; - } - friend constexpr ptrdiff_t operator-( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return i.ptr_ - j.ptr_; - } - - friend constexpr boolean_testable_result operator==( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ == j.ptr_}; - } - - friend constexpr boolean_testable_result operator!=( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ != j.ptr_}; - } - - friend constexpr boolean_testable_result operator<( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ < j.ptr_}; - } - - friend constexpr boolean_testable_result operator>( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ > j.ptr_}; - } - - friend constexpr boolean_testable_result operator<=( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ <= j.ptr_}; - } - - friend constexpr boolean_testable_result operator>=( - const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ <= j.ptr_}; - } - - int* ptr_; -}; - -struct validating_negation_view { - constexpr negation_validating_iterator begin() const noexcept { - return {begin_}; - } - - constexpr negation_validating_iterator end() const noexcept { - return {end_}; - } - - int* begin_; - int* end_; -}; - -template <> -inline constexpr bool ranges::enable_view = true; - -template <> -inline constexpr bool ranges::enable_borrowed_range = true; - -template -void test_adl_proof_random_access_views_comparison(V&& v) { - auto i = v.begin(); - auto j = v.end(); - - (void) (i == j); - (void) (i != j); - (void) (i < j); - (void) (i > j); - (void) (i <= j); - (void) (i >= j); -} - -template -void test_adl_proof_basic_views_comparison(V&& v) { - auto it = v.begin(); - auto se = v.end(); - - (void) (it == se); - (void) (it != se); -} - -void test_adl_proof_views_comparison() { - constexpr auto simple_truth = [](const auto&) { return true; }; - - int iarr[1]{}; - const validating_common_view validating_common_view_val{iarr, iarr + 1}; - const validating_noncommon_view validating_noncommon_view_val{iarr, iarr + 1}; - const validating_negation_view validating_negation_view_val{iarr, iarr + 1}; - const validating_noncommon_to_join_view validating_view_to_join{ - &validating_noncommon_view_val, &validating_noncommon_view_val + 1}; - - test_adl_proof_basic_views_comparison(validating_common_view_val | views::filter(simple_truth)); - test_adl_proof_basic_views_comparison(validating_negation_view_val | views::filter(simple_truth)); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::filter(simple_truth)); - - test_adl_proof_basic_views_comparison(validating_view_to_join | views::join); - - test_adl_proof_basic_views_comparison(validating_common_view_val | views::split(validating_common_view_val)); - test_adl_proof_basic_views_comparison(validating_negation_view_val | views::split(validating_negation_view_val)); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::split(validating_noncommon_view_val)); - - test_adl_proof_basic_views_comparison(validating_common_view_val | views::lazy_split(validating_common_view_val)); - test_adl_proof_basic_views_comparison( - validating_negation_view_val | views::lazy_split(validating_negation_view_val)); - test_adl_proof_basic_views_comparison( - validating_noncommon_view_val | views::lazy_split(validating_noncommon_view_val)); - -#if _HAS_CXX23 - test_adl_proof_basic_views_comparison(validating_view_to_join | views::join_with(validating_noncommon_view_val)); - - test_adl_proof_random_access_views_comparison(validating_common_view_val | views::enumerate); - test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::enumerate); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::enumerate); - - test_adl_proof_random_access_views_comparison(validating_common_view_val | views::chunk(1)); - test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::chunk(1)); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::chunk(1)); - - test_adl_proof_random_access_views_comparison(validating_common_view_val | views::slide(1)); - test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::slide(1)); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::slide(1)); - - test_adl_proof_basic_views_comparison(validating_common_view_val | views::chunk_by(ranges::equal_to{})); - test_adl_proof_basic_views_comparison(validating_negation_view_val | views::chunk_by(ranges::equal_to{})); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::chunk_by(ranges::equal_to{})); - - test_adl_proof_random_access_views_comparison(validating_common_view_val | views::stride(1)); - test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::stride(1)); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::stride(1)); - - test_adl_proof_random_access_views_comparison(validating_common_view_val | views::adjacent<1>); - test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::adjacent<1>); - test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::adjacent<1>); -#endif // _HAS_CXX23 -} -#endif // _HAS_CXX20 - #if _HAS_CXX23 void test_adl_proof_expected_comparison() { expected ex; diff --git a/tests/std/tests/GH_000140_adl_proof_views/env.lst b/tests/std/tests/GH_000140_adl_proof_views/env.lst new file mode 100644 index 00000000000..7b6bcff4830 --- /dev/null +++ b/tests/std/tests/GH_000140_adl_proof_views/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_20_matrix.lst diff --git a/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp b/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp new file mode 100644 index 00000000000..c70ff4267ff --- /dev/null +++ b/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp @@ -0,0 +1,525 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef _M_CEE // TRANSITION, VSO-1659496 +#include +#include +#include +#include +#include + +using namespace std; + +template +struct holder { + T t; +}; + +struct incomplete; + +constexpr holder* placeholder = nullptr; +constexpr holder* const* placeholder_addr = &placeholder; + +template +struct validating_iterator_provider { + struct iterator; +}; + +template +concept validating_iterator_specialization = requires { + typename I::reference; +} && same_as>::iterator>; + +template +struct validating_iterator_provider::iterator { + using value_type = remove_cv_t; + using pointer = T*; + using reference = T&; + using difference_type = ptrdiff_t; + using iterator_category = random_access_iterator_tag; +#if _HAS_CXX20 + using iterator_concept = contiguous_iterator_tag; +#endif // _HAS_CXX20 + + constexpr T& operator*() const noexcept { + return *ptr_; + } + + constexpr T* operator->() const noexcept { + return ptr_; + } + + constexpr T& operator[](const ptrdiff_t n) const noexcept { + return ptr_[n]; + } + + constexpr iterator& operator++() noexcept { + ++ptr_; + return *this; + } + constexpr iterator operator++(int) noexcept { + auto old = *this; + ++*this; + return old; + } + + constexpr iterator& operator--() noexcept { + --ptr_; + return *this; + } + constexpr iterator operator--(int) noexcept { + auto old = *this; + --*this; + return old; + } + + constexpr iterator& operator+=(const ptrdiff_t n) noexcept { + ptr_ += n; + return *this; + } + + constexpr iterator& operator-=(const ptrdiff_t n) noexcept { + ptr_ -= n; + return *this; + } + + friend constexpr iterator operator+(const iterator i, const ptrdiff_t n) noexcept { + return {i.ptr_ + n}; + } + friend constexpr iterator operator+(const ptrdiff_t n, const iterator i) noexcept { + return {i.ptr_ + n}; + } + + friend constexpr ptrdiff_t operator-(const iterator i, const iterator j) noexcept { + return i.ptr_ - j.ptr_; + } + friend constexpr iterator operator-(const iterator i, const ptrdiff_t n) noexcept { + return iterator{i.ptr_ - n}; + } + + template + friend constexpr decltype(auto) operator==(iterator i, OtherIter j) noexcept + requires requires { pointer{} == typename OtherIter::pointer{} ? placeholder_addr : nullptr; } + { + return i.operator->() == j.operator->() ? placeholder_addr : nullptr; + } + template + friend constexpr decltype(auto) operator!=(iterator i, OtherIter j) noexcept + requires requires { pointer{} != typename OtherIter::pointer{} ? placeholder_addr : nullptr; } + { + return i.operator->() != j.operator->() ? placeholder_addr : nullptr; + } + + template + friend constexpr decltype(auto) operator<(iterator i, OtherIter j) noexcept + requires requires { pointer{} < typename OtherIter::pointer{} ? placeholder_addr : nullptr; } + { + return i.operator->() < j.operator->() ? placeholder_addr : nullptr; + } + template + friend constexpr decltype(auto) operator>(iterator i, OtherIter j) noexcept + requires requires { pointer{} > typename OtherIter::pointer{} ? placeholder_addr : nullptr; } + { + return i.operator->() > j.operator->() ? placeholder_addr : nullptr; + } + template + friend constexpr decltype(auto) operator<=(iterator i, OtherIter j) + requires requires { pointer{} <= typename OtherIter::pointer{} ? placeholder_addr : nullptr; } + { + return i.operator->() <= j.operator->() ? placeholder_addr : nullptr; + } + template + friend constexpr decltype(auto) operator>=(iterator i, OtherIter j) noexcept + requires requires { pointer{} >= typename OtherIter::pointer{} ? placeholder_addr : nullptr; } + { + return i.operator->() >= j.operator->() ? placeholder_addr : nullptr; + } + + template + requires (!is_same_v) && convertible_to + constexpr operator OtherIter() const noexcept { + return {ptr_}; + } + + T* ptr_; +}; + +struct validating_view_for_verification { + constexpr holder** begin() const noexcept { + return begin_; + } + + constexpr holder** end() const noexcept { + return end_; + } + + holder** begin_; + holder** end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template +struct tagged_ints_view { + constexpr int* begin() const noexcept { + return begin_; + } + + constexpr int* end() const noexcept { + return end_; + } + + int* begin_; + int* end_; +}; + +template +inline constexpr bool ranges::enable_view> = true; + +template +inline constexpr bool ranges::enable_borrowed_range> = true; + +struct validating_view_to_join_for_verification { + constexpr const tagged_ints_view>* begin() const noexcept { + return begin_; + } + + constexpr const tagged_ints_view>* end() const noexcept { + return end_; + } + + const tagged_ints_view>* begin_; + const tagged_ints_view>* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +void test_views_verification() { + constexpr auto simple_truth = [](const auto&) { return true; }; + + holder* varr[1]{}; + const validating_view_for_verification validating_view_val{varr, varr + 1}; + + for (auto&& _ [[maybe_unused]] : validating_view_val | views::filter(simple_truth)) + ; + + for (auto&& _ [[maybe_unused]] : validating_view_val | views::transform(simple_truth)) + ; + + int iarr[1]{}; + const tagged_ints_view> inner_arr[1]{{iarr, iarr + 1}}; + const validating_view_to_join_for_verification view_to_join{inner_arr, inner_arr + 1}; + + for (auto&& _ [[maybe_unused]] : view_to_join | views::join) + ; + + for (auto&& _ [[maybe_unused]] : view_to_join | views::join | views::reverse) + ; + +#if _HAS_CXX23 + const tagged_ints_view simple_pattern{iarr, iarr + 1}; + + for (auto&& _ [[maybe_unused]] : view_to_join | views::join_with(simple_pattern)) + ; +#endif // _HAS_CXX23 +} + +struct validating_common_view { + using iterator = validating_iterator_provider::iterator; + + constexpr iterator begin() const noexcept { + return {begin_}; + } + + constexpr iterator end() const noexcept { + return {end_}; + } + + int* begin_; + int* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template +struct noncommon_sentinel_for { + using pointer = iterator_traits::pointer; + + pointer p_end_; + + friend constexpr holder* const* operator==(const I i, const noncommon_sentinel_for s) noexcept { + return to_address(i) == s.p_end_ ? placeholder_addr : nullptr; + } + friend constexpr holder* const* operator==(const noncommon_sentinel_for s, const I i) noexcept { + return to_address(i) == s.p_end_ ? placeholder_addr : nullptr; + } + friend constexpr holder* const* operator!=(const I i, const noncommon_sentinel_for s) noexcept { + return to_address(i) == s.p_end_ ? nullptr : placeholder_addr; + } + friend constexpr holder* const* operator!=(const noncommon_sentinel_for s, const I i) noexcept { + return to_address(i) == s.p_end_ ? nullptr : placeholder_addr; + } +}; + +struct validating_noncommon_view { + using iterator = validating_iterator_provider::iterator; + + constexpr iterator begin() const noexcept { + return {begin_}; + } + + constexpr noncommon_sentinel_for end() const noexcept { + return {end_}; + } + + int* begin_; + int* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + + +struct validating_noncommon_to_join_view { + using iterator = const validating_noncommon_view*; + + constexpr iterator begin() const noexcept { + return begin_; + } + + constexpr noncommon_sentinel_for end() const noexcept { + return {end_}; + } + + const validating_noncommon_view* begin_; + const validating_noncommon_view* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +struct negation_validating_iterator { + struct boolean_testable_result { + constexpr operator bool() const noexcept { + return val_; + } + + constexpr holder* const* operator!() const noexcept { + return val_ ? placeholder_addr : nullptr; + } + bool val_; + }; + + using value_type = int; + using reference = int&; + using pointer = int*; + using difference_type = ptrdiff_t; + using iterator_category = random_access_iterator_tag; + using iterator_concept = contiguous_iterator_tag; + + constexpr int& operator*() const noexcept { + return *ptr_; + } + + constexpr int* operator->() const noexcept { + return ptr_; + } + + constexpr negation_validating_iterator& operator++() noexcept { + ++ptr_; + return *this; + } + constexpr negation_validating_iterator operator++(int) noexcept { + auto old = *this; + ++ptr_; + return old; + } + + constexpr negation_validating_iterator& operator--() noexcept { + --ptr_; + return *this; + } + constexpr negation_validating_iterator operator--(int) noexcept { + auto old = *this; + --ptr_; + return old; + } + + constexpr negation_validating_iterator& operator+=(const ptrdiff_t n) noexcept { + ptr_ += n; + return *this; + } + + constexpr negation_validating_iterator& operator-=(const ptrdiff_t n) noexcept { + ptr_ -= n; + return *this; + } + + constexpr int& operator[](const ptrdiff_t n) const noexcept { + return ptr_[n]; + } + + friend constexpr negation_validating_iterator operator+( + const negation_validating_iterator i, const ptrdiff_t n) noexcept { + return {i.ptr_ + n}; + } + friend constexpr negation_validating_iterator operator+( + const ptrdiff_t n, const negation_validating_iterator i) noexcept { + return {i.ptr_ + n}; + } + friend constexpr negation_validating_iterator operator-( + const negation_validating_iterator i, const ptrdiff_t n) noexcept { + return {i.ptr_ - n}; + } + friend constexpr ptrdiff_t operator-( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return i.ptr_ - j.ptr_; + } + + friend constexpr boolean_testable_result operator==( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ == j.ptr_}; + } + + friend constexpr boolean_testable_result operator!=( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ != j.ptr_}; + } + + friend constexpr boolean_testable_result operator<( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ < j.ptr_}; + } + + friend constexpr boolean_testable_result operator>( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ > j.ptr_}; + } + + friend constexpr boolean_testable_result operator<=( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ <= j.ptr_}; + } + + friend constexpr boolean_testable_result operator>=( + const negation_validating_iterator i, const negation_validating_iterator j) noexcept { + return {i.ptr_ <= j.ptr_}; + } + + int* ptr_; +}; + +struct validating_negation_view { + constexpr negation_validating_iterator begin() const noexcept { + return {begin_}; + } + + constexpr negation_validating_iterator end() const noexcept { + return {end_}; + } + + int* begin_; + int* end_; +}; + +template <> +inline constexpr bool ranges::enable_view = true; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template +void test_adl_proof_random_access_views_comparison(V&& v) { + auto i = v.begin(); + auto j = v.end(); + + (void) (i == j); + (void) (i != j); + (void) (i < j); + (void) (i > j); + (void) (i <= j); + (void) (i >= j); +} + +template +void test_adl_proof_basic_views_comparison(V&& v) { + auto it = v.begin(); + auto se = v.end(); + + (void) (it == se); + (void) (it != se); +} + +void test_adl_proof_views_comparison() { + constexpr auto simple_truth = [](const auto&) { return true; }; + + int iarr[1]{}; + const validating_common_view validating_common_view_val{iarr, iarr + 1}; + const validating_noncommon_view validating_noncommon_view_val{iarr, iarr + 1}; + const validating_negation_view validating_negation_view_val{iarr, iarr + 1}; + const validating_noncommon_to_join_view validating_view_to_join{ + &validating_noncommon_view_val, &validating_noncommon_view_val + 1}; + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::filter(simple_truth)); + test_adl_proof_basic_views_comparison(validating_negation_view_val | views::filter(simple_truth)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::filter(simple_truth)); + + test_adl_proof_basic_views_comparison(validating_view_to_join | views::join); + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::split(validating_common_view_val)); + test_adl_proof_basic_views_comparison(validating_negation_view_val | views::split(validating_negation_view_val)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::split(validating_noncommon_view_val)); + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::lazy_split(validating_common_view_val)); + test_adl_proof_basic_views_comparison( + validating_negation_view_val | views::lazy_split(validating_negation_view_val)); + test_adl_proof_basic_views_comparison( + validating_noncommon_view_val | views::lazy_split(validating_noncommon_view_val)); + +#if _HAS_CXX23 + test_adl_proof_basic_views_comparison(validating_view_to_join | views::join_with(validating_noncommon_view_val)); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::enumerate); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::enumerate); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::enumerate); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::chunk(1)); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::chunk(1)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::chunk(1)); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::slide(1)); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::slide(1)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::slide(1)); + + test_adl_proof_basic_views_comparison(validating_common_view_val | views::chunk_by(ranges::equal_to{})); + test_adl_proof_basic_views_comparison(validating_negation_view_val | views::chunk_by(ranges::equal_to{})); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::chunk_by(ranges::equal_to{})); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::stride(1)); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::stride(1)); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::stride(1)); + + test_adl_proof_random_access_views_comparison(validating_common_view_val | views::adjacent<1>); + test_adl_proof_random_access_views_comparison(validating_negation_view_val | views::adjacent<1>); + test_adl_proof_basic_views_comparison(validating_noncommon_view_val | views::adjacent<1>); +#endif // _HAS_CXX23 +} +#endif // ^^^ no workaround ^^^ From cb1a5e3ddf43af462106d2d2009a8149b9c54568 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 15 Feb 2024 15:01:13 -0800 Subject: [PATCH 3/3] Code review feedback. --- .../test.compile.pass.cpp | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp b/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp index c70ff4267ff..624b6e42d37 100644 --- a/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp +++ b/tests/std/tests/GH_000140_adl_proof_views/test.compile.pass.cpp @@ -4,6 +4,7 @@ #ifndef _M_CEE // TRANSITION, VSO-1659496 #include #include +#include #include #include #include @@ -37,9 +38,7 @@ struct validating_iterator_provider::iterator { using reference = T&; using difference_type = ptrdiff_t; using iterator_category = random_access_iterator_tag; -#if _HAS_CXX20 - using iterator_concept = contiguous_iterator_tag; -#endif // _HAS_CXX20 + using iterator_concept = contiguous_iterator_tag; constexpr T& operator*() const noexcept { return *ptr_; @@ -208,27 +207,27 @@ void test_views_verification() { holder* varr[1]{}; const validating_view_for_verification validating_view_val{varr, varr + 1}; - for (auto&& _ [[maybe_unused]] : validating_view_val | views::filter(simple_truth)) - ; + for (auto&& _ [[maybe_unused]] : validating_view_val | views::filter(simple_truth)) { + } - for (auto&& _ [[maybe_unused]] : validating_view_val | views::transform(simple_truth)) - ; + for (auto&& _ [[maybe_unused]] : validating_view_val | views::transform(simple_truth)) { + } int iarr[1]{}; const tagged_ints_view> inner_arr[1]{{iarr, iarr + 1}}; const validating_view_to_join_for_verification view_to_join{inner_arr, inner_arr + 1}; - for (auto&& _ [[maybe_unused]] : view_to_join | views::join) - ; + for (auto&& _ [[maybe_unused]] : view_to_join | views::join) { + } - for (auto&& _ [[maybe_unused]] : view_to_join | views::join | views::reverse) - ; + for (auto&& _ [[maybe_unused]] : view_to_join | views::join | views::reverse) { + } #if _HAS_CXX23 const tagged_ints_view simple_pattern{iarr, iarr + 1}; - for (auto&& _ [[maybe_unused]] : view_to_join | views::join_with(simple_pattern)) - ; + for (auto&& _ [[maybe_unused]] : view_to_join | views::join_with(simple_pattern)) { + } #endif // _HAS_CXX23 } @@ -421,7 +420,7 @@ struct negation_validating_iterator { friend constexpr boolean_testable_result operator>=( const negation_validating_iterator i, const negation_validating_iterator j) noexcept { - return {i.ptr_ <= j.ptr_}; + return {i.ptr_ >= j.ptr_}; } int* ptr_;