diff --git a/stl/inc/concepts b/stl/inc/concepts index 4da6a23f497..fad9a75caa8 100644 --- a/stl/inc/concepts +++ b/stl/inc/concepts @@ -165,9 +165,10 @@ namespace ranges { }; } // namespace _Swap - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Swap::_Cpo swap; } + using namespace _Cpos; } // namespace ranges // CONCEPT swappable diff --git a/stl/inc/ranges b/stl/inc/ranges index 5964866450e..ead69fbcd17 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -33,10 +33,192 @@ namespace ranges { concept viewable_range = range<_Rng> && (borrowed_range<_Rng> || view>); + template + concept _Simple_view = view<_Rng> && range + && same_as, iterator_t> + && same_as, sentinel_t>; + template concept _Copy_constructible_object = copy_constructible<_Ty> && is_object_v<_Ty>; // clang-format on + namespace _Pipe { + // clang-format off + template + concept _Can_pipe = requires(_Left&& __l, _Right&& __r) { + static_cast<_Right&&>(__r)(static_cast<_Left&&>(__l)); + }; + + template + concept _Can_compose = constructible_from, _Left> + && constructible_from, _Right>; + // clang-format on + + template + struct _Pipeline; + + template + struct _Base { + // clang-format off + template + requires _Can_compose<_Derived, _Other> + constexpr auto operator|(_Base<_Other>&& __r) && noexcept( + noexcept(_Pipeline{static_cast<_Derived&&>(*this), static_cast<_Other&&>(__r)})) { + // clang-format on + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>); + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>); + return _Pipeline{static_cast<_Derived&&>(*this), static_cast<_Other&&>(__r)}; + } + + // clang-format off + template + requires _Can_compose<_Derived, const _Other&> + constexpr auto operator|(const _Base<_Other>& __r) && noexcept(noexcept( + _Pipeline{static_cast<_Derived&&>(*this), static_cast(__r)})) { + // clang-format on + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>); + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>); + return _Pipeline{static_cast<_Derived&&>(*this), static_cast(__r)}; + } + + // clang-format off + template + requires _Can_compose + constexpr auto operator|(_Base<_Other>&& __r) const& noexcept( + noexcept(_Pipeline{static_cast(*this), static_cast<_Other&&>(__r)})) { + // clang-format on + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>); + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>); + return _Pipeline{static_cast(*this), static_cast<_Other&&>(__r)}; + } + + // clang-format off + template + requires _Can_compose + constexpr auto operator|(const _Base<_Other>& __r) const& noexcept(noexcept( + _Pipeline{static_cast(*this), static_cast(__r)})) { + // clang-format on + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Derived, _Base<_Derived>>); + _STL_INTERNAL_STATIC_ASSERT(derived_from<_Other, _Base<_Other>>); + return _Pipeline{static_cast(*this), static_cast(__r)}; + } + + template <_Can_pipe _Left> + friend constexpr auto operator|(_Left&& __l, const _Base& __r) noexcept( + noexcept(static_cast(__r)(_STD forward<_Left>(__l)))) { + return static_cast(__r)(_STD forward<_Left>(__l)); + } + + template <_Can_pipe<_Derived> _Left> + friend constexpr auto operator|(_Left&& __l, _Base&& __r) noexcept( + noexcept(static_cast<_Derived&&>(__r)(_STD forward<_Left>(__l)))) { + return static_cast<_Derived&&>(__r)(_STD forward<_Left>(__l)); + } + }; + + template + struct _Pipeline : _Base<_Pipeline<_Left, _Right>> { + /* [[no_unique_address]] */ _Left __l; + /* [[no_unique_address]] */ _Right __r; + + template + constexpr explicit _Pipeline(_Ty1&& _Val1, _Ty2&& _Val2) noexcept( + is_nothrow_convertible_v<_Ty1, _Left>&& is_nothrow_convertible_v<_Ty2, _Right>) + : __l(_STD forward<_Ty1>(_Val1)), __r(_STD forward<_Ty2>(_Val2)) {} + + template + _NODISCARD constexpr auto operator()(_Ty&& _Val) noexcept( + noexcept(__r(__l(_STD forward<_Ty>(_Val))))) requires requires { + __r(__l(static_cast<_Ty&&>(_Val))); + } + { return __r(__l(_STD forward<_Ty>(_Val))); } + + template + _NODISCARD constexpr auto operator()(_Ty&& _Val) const + noexcept(noexcept(__r(__l(_STD forward<_Ty>(_Val))))) requires requires { + __r(__l(static_cast<_Ty&&>(_Val))); + } + { return __r(__l(_STD forward<_Ty>(_Val))); } + }; + + template + _Pipeline(_Ty1, _Ty2) -> _Pipeline<_Ty1, _Ty2>; + } // namespace _Pipe + + template + class _Cached_position : public view_interface<_Derived> { + static_assert(_Always_false<_Rng>, "A range must be at least forward for position caching to be worthwhile."); + }; + + template + class _Cached_position<_Rng, _Derived> : public view_interface<_Derived> { + private: + using _It = iterator_t<_Rng>; + + /* [[no_unique_address]] */ _It _Pos{}; + bool _Cached = false; + + protected: + _Cached_position() = default; + ~_Cached_position() = default; + + // a copied iterator doesn't point into a copied range, so cache values must not propagate via copy + constexpr _Cached_position(const _Cached_position&) noexcept(is_nothrow_default_constructible_v<_It>) {} + constexpr _Cached_position& operator=(const _Cached_position&) noexcept( + is_nothrow_default_constructible_v<_It>) { + _Pos = _It{}; + _Cached = false; + return *this; + } + + _NODISCARD constexpr bool _Has_cache() const noexcept { // Is there a cached position? + return _Cached; + } + + _NODISCARD constexpr _It _Get_cache(_Rng&) const noexcept(is_nothrow_copy_constructible_v<_It>) { + _STL_INTERNAL_CHECK(_Cached); + return _Pos; + } + + _NODISCARD constexpr void _Set_cache(_Rng&, _It _Iter) noexcept(is_nothrow_move_assignable_v<_It>) { + _Pos = _STD move(_Iter); + _Cached = true; + } + }; + + template + class _Cached_position<_Rng, _Derived> : public view_interface<_Derived> { + private: + using _It = iterator_t<_Rng>; + + range_difference_t<_Rng> _Off = -1; + + protected: + _Cached_position() = default; + ~_Cached_position() = default; + + // Offsets are oblivious to copying, so cache values _do_ propagate via copying. + _Cached_position(const _Cached_position&) = default; + _Cached_position& operator=(const _Cached_position&) = default; + + _NODISCARD constexpr bool _Has_cache() const noexcept { // Is there a cached position? + return _Off >= range_difference_t<_Rng>{0}; + } + + _NODISCARD constexpr _It _Get_cache(_Rng& _Range) const noexcept(noexcept(_RANGES begin(_Range) + _Off)) { + _STL_INTERNAL_CHECK(_Has_cache()); + return _RANGES begin(_Range) + _Off; + } + + _NODISCARD constexpr void _Set_cache(_Rng& _Range, const _It& _Iter) noexcept( + noexcept(_Off = _Iter - _RANGES begin(_Range))) { + _Off = _Iter - _RANGES begin(_Range); + } + }; + + template + using _Cached_position_t = conditional_t<_Enable, _Cached_position<_Rng, _Derived>, view_interface<_Derived>>; + // CLASS TEMPLATE ranges::_Semiregular_box #if 0 // TRANSITION, VSO-1174090 template <_Copy_constructible_object _Ty> @@ -417,10 +599,10 @@ namespace ranges { // clang-format off template _NODISCARD constexpr auto operator()(_Ty&& _Val) const noexcept( - noexcept(single_view{static_cast<_Ty&&>(_Val)})) requires requires { + noexcept(single_view{_STD forward<_Ty>(_Val)})) requires requires { single_view{static_cast<_Ty&&>(_Val)}; } { - return single_view{static_cast<_Ty&&>(_Val)}; + return single_view{_STD forward<_Ty>(_Val)}; } // clang-format on }; @@ -486,6 +668,210 @@ namespace ranges { template inline constexpr bool enable_borrowed_range> = true; + + namespace views { + // VARIABLE views::all + template + concept _Can_ref_view = requires(_Rng&& __r) { + ref_view{static_cast<_Rng&&>(__r)}; + }; + + template + concept _Can_subrange = requires(_Rng&& __r) { + subrange{static_cast<_Rng&&>(__r)}; + }; + + class _All_fn : public _Pipe::_Base<_All_fn> { + private: + enum class _St { _None, _View, _Ref, _Subrange }; + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (view>) { + if constexpr (constructible_from, _Rng>) { + return {_St::_View, is_nothrow_constructible_v, _Rng>}; + } + } else if constexpr (_Can_ref_view<_Rng>) { + return {_St::_Ref, noexcept(ref_view{_STD declval<_Rng>()})}; + } else if constexpr (_Can_subrange<_Rng>) { + return {_St::_Subrange, noexcept(subrange{_STD declval<_Rng>()})}; + } + + return {_St::_None}; + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); + + public: + // clang-format off + template + requires (_Choice<_Rng>._Strategy != _St::_None) + _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { + // clang-format on + if constexpr (_Choice<_Rng>._Strategy == _St::_View) { + return _STD forward<_Rng>(_Range); + } else if constexpr (_Choice<_Rng>._Strategy == _St::_Ref) { + return ref_view{_STD forward<_Rng>(_Range)}; + } else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange) { + return subrange{_STD forward<_Rng>(_Range)}; + } else { + static_assert(_Always_false<_Rng>, "Should be unreachable"); + } + } + }; + + inline constexpr _All_fn all; + + // ALIAS TEMPLATE views::all_t + template + using all_t = decltype(all(_STD declval<_Rng>())); + } // namespace views + + // CLASS TEMPLATE ranges::reverse_view + // clang-format off + template + requires bidirectional_range<_Vw> + class reverse_view : public _Cached_position_t, _Vw, reverse_view<_Vw>> { + // clang-format on + private: + /* [[no_unique_address]] */ _Vw _Base{}; + + template + using _Rev_iter = reverse_iterator>; + + public: + reverse_view() = default; + constexpr explicit reverse_view(_Vw _Base_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened + : _Base(_STD move(_Base_)) {} + + _NODISCARD constexpr _Vw base() const& noexcept( + is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> { + return _Base; + } + _NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ { + return _STD move(_Base); + } + + _NODISCARD constexpr _Rev_iter<_Vw> begin() { + if constexpr (common_range<_Vw>) { + return _Rev_iter<_Vw>{_RANGES end(_Base)}; + } else { + if (this->_Has_cache()) { + return _Rev_iter<_Vw>{this->_Get_cache(_Base)}; + } + + iterator_t<_Vw> _First; + if constexpr (sized_range<_Vw>) { + _First = _RANGES next(_RANGES begin(_Base), _RANGES distance(_Base)); + } else { + _First = _RANGES next(_RANGES begin(_Base), _RANGES end(_Base)); + } + this->_Set_cache(_Base, _First); + return _Rev_iter<_Vw>{_STD move(_First)}; + } + } + + _NODISCARD constexpr auto begin() const noexcept( + noexcept(_Rev_iter{_RANGES end(_Base)})) /* strengthened */ requires common_range { + return _Rev_iter{_RANGES end(_Base)}; + } + + _NODISCARD constexpr _Rev_iter<_Vw> end() noexcept( + noexcept(_Rev_iter<_Vw>{_RANGES begin(_Base)})) /* strengthened */ { + return _Rev_iter<_Vw>{_RANGES begin(_Base)}; + } + _NODISCARD constexpr auto end() const noexcept( + noexcept(_Rev_iter{_RANGES begin(_Base)})) /* strengthened */ requires common_range { + return _Rev_iter{_RANGES begin(_Base)}; + } + + _NODISCARD constexpr auto size() noexcept( + noexcept(_RANGES size(_Base))) /* strengthened */ requires sized_range<_Vw> { + return _RANGES size(_Base); + } + _NODISCARD constexpr auto size() const + noexcept(noexcept(_RANGES size(_Base))) /* strengthened */ requires sized_range { + return _RANGES size(_Base); + } + }; + + template + reverse_view(_Rng &&) -> reverse_view>; + + namespace views { + // VARIABLE views::reverse + template + concept _Can_extract_base = requires(_Rng&& __r) { + static_cast<_Rng&&>(__r).base(); + }; + + template + concept _Can_reverse = requires(_Rng&& __r) { + reverse_view{static_cast<_Rng&&>(__r)}; + }; + + class _Reverse_fn : public _Pipe::_Base<_Reverse_fn> { + private: + enum class _St { _None, _Base, _Subrange_unsized, _Subrange_sized, _Reverse }; + + template + static constexpr auto _Reversed_subrange = -1; + + template + static constexpr auto + _Reversed_subrange, reverse_iterator<_It>, _Ki>> = static_cast(_Ki); + + template + _NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept { + if constexpr (bidirectional_range<_Rng>) { + if constexpr (_Is_specialization_v<_Rng, reverse_view>) { + if constexpr (_Can_extract_base<_Rng>) { + return {_St::_Base, noexcept(_STD declval<_Rng>().base())}; + } + } else if constexpr (_Reversed_subrange> == 0) { + using _It = decltype(_STD declval<_Rng&>().begin().base()); + return {_St::_Subrange_unsized, + noexcept(subrange<_It, _It, subrange_kind::unsized>{ + _STD declval<_Rng&>().end().base(), _STD declval<_Rng&>().begin().base()})}; + } else if constexpr (_Reversed_subrange> == 1) { + using _It = decltype(_STD declval<_Rng&>().begin().base()); + return {_St::_Subrange_sized, + noexcept(subrange<_It, _It, subrange_kind::sized>{_STD declval<_Rng&>().end().base(), + _STD declval<_Rng&>().begin().base(), _STD declval<_Rng&>().size()})}; + } else if constexpr (_Can_reverse<_Rng>) { + return {_St::_Reverse, noexcept(reverse_view{_STD declval<_Rng>()})}; + } + } + + return {_St::_None}; + } + + template + static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>(); + + public: + // clang-format off + template + requires (_Choice<_Rng>._Strategy != _St::_None) + _NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) { + // clang-format on + if constexpr (_Choice<_Rng>._Strategy == _St::_Base) { + return _STD forward<_Rng>(_Range).base(); + } else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange_unsized) { + return subrange{_Range.end().base(), _Range.begin().base()}; + } else if constexpr (_Choice<_Rng>._Strategy == _St::_Subrange_sized) { + return subrange{_Range.end().base(), _Range.begin().base(), _Range.size()}; + } else if constexpr (_Choice<_Rng>._Strategy == _St::_Reverse) { + return reverse_view{_STD forward<_Rng>(_Range)}; + } else { + static_assert(_Always_false<_Rng>, "Should be unreachable"); + } + } + }; + + inline constexpr _Reverse_fn reverse; + } // namespace views } // namespace ranges namespace views = ranges::views; diff --git a/stl/inc/xstring b/stl/inc/xstring index 5cd221c2f72..6e2f92e1405 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -1048,7 +1048,7 @@ public: constexpr _String_view_iterator& operator+=(const difference_type _Off) noexcept { #if _ITERATOR_DEBUG_LEVEL >= 1 _Verify_offset(_Off); - _Myoff += _Off; + _Myoff += static_cast(_Off); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv _Myptr += _Off; #endif // _ITERATOR_DEBUG_LEVEL @@ -1077,7 +1077,7 @@ public: "cannot seek string_view iterator after end"); } - _Myoff -= _Off; + _Myoff -= static_cast(_Off); #else // ^^^ _ITERATOR_DEBUG_LEVEL >= 1 ^^^ // vvv _ITERATOR_DEBUG_LEVEL == 0 vvv _Myptr -= _Off; #endif // _ITERATOR_DEBUG_LEVEL diff --git a/stl/inc/xutility b/stl/inc/xutility index 7a08e0a3cc5..2c9fc57aa95 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -645,7 +645,7 @@ struct iterator_traits<_Ty*> { }; // clang-format on -// CUSTOMIZATION POINT OBJECT iter_move +// CUSTOMIZATION POINT OBJECT ranges::iter_move namespace ranges { // STRUCT TEMPLATE _Choice_t template @@ -707,9 +707,10 @@ namespace ranges { // clang-format on } // namespace _Iter_move - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Iter_move::_Cpo iter_move; } + using namespace _Cpos; } // namespace ranges // iter_swap defined below since it depends on indirectly_movable_storable @@ -1017,7 +1018,7 @@ concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> && assignable_from&, iter_reference_t<_In>>; // clang-format on -// CUSTOMIZATION POINT OBJECT iter_swap +// CUSTOMIZATION POINT OBJECT ranges::iter_swap namespace ranges { namespace _Iter_swap { template @@ -1091,9 +1092,10 @@ namespace ranges { }; } // namespace _Iter_swap - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Iter_swap::_Cpo iter_swap; } + using namespace _Cpos; } // namespace ranges // clang-format off @@ -2408,9 +2410,10 @@ namespace ranges { }; } // namespace _Begin - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Begin::_Cpo begin; } + using namespace _Cpos; // ALIAS TEMPLATE ranges::iterator_t template @@ -2468,9 +2471,10 @@ namespace ranges { }; } // namespace _Unchecked_begin - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Unchecked_begin::_Cpo _Ubegin; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::end namespace _End { @@ -2542,9 +2546,10 @@ namespace ranges { }; } // namespace _End - inline namespace _Cpos { + namespace _Cpos { inline constexpr _End::_Cpo end; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::_Uend namespace _Unchecked_end { @@ -2599,9 +2604,10 @@ namespace ranges { }; } // namespace _Unchecked_end - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Unchecked_end::_Cpo _Uend; } + using namespace _Cpos; // CONCEPT ranges::range template @@ -2648,9 +2654,10 @@ namespace ranges { // clang-format on }; - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Cbegin_fn cbegin; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::cend struct _Cend_fn { @@ -2664,9 +2671,10 @@ namespace ranges { // clang-format on }; - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Cend_fn cend; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::rbegin namespace _Rbegin { @@ -2733,9 +2741,10 @@ namespace ranges { }; } // namespace _Rbegin - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Rbegin::_Cpo rbegin; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::rend namespace _Rend { @@ -2803,9 +2812,10 @@ namespace ranges { }; } // namespace _Rend - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Rend::_Cpo rend; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::crbegin struct _Crbegin_fn { @@ -2819,9 +2829,10 @@ namespace ranges { // clang-format on }; - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Crbegin_fn crbegin; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::crend struct _Crend_fn { @@ -2835,9 +2846,10 @@ namespace ranges { // clang-format on }; - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Crend_fn crend; } + using namespace _Cpos; // VARIABLE TEMPLATE ranges::disable_sized_range template @@ -2921,9 +2933,10 @@ namespace ranges { }; } // namespace _Size - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Size::_Cpo size; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::empty namespace _Empty { @@ -2989,9 +3002,10 @@ namespace ranges { }; } // namespace _Empty - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Empty::_Cpo empty; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::data namespace _Data { @@ -3046,9 +3060,10 @@ namespace ranges { }; } // namespace _Data - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Data::_Cpo data; } + using namespace _Cpos; // CUSTOMIZATION POINT OBJECT ranges::cdata struct _Cdata_fn { @@ -3062,9 +3077,10 @@ namespace ranges { // clang-format on }; - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Cdata_fn cdata; } + using namespace _Cpos; // clang-format off // CONCEPT ranges::sized_range @@ -3289,9 +3305,10 @@ namespace ranges { // clang-format on }; - inline namespace _Cpos { + namespace _Cpos { inline constexpr _Ssize_fn ssize; } + using namespace _Cpos; // VARIABLE ranges::next class _Next_fn : private _Not_quite_object { @@ -3584,7 +3601,9 @@ namespace ranges { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (sized_range<_Derived>) { - _STL_VERIFY(_Idx < _RANGES size(_Self), "index out of range for view_interface"); + using _U_diff = _Make_unsigned_like_t>; + _STL_VERIFY(static_cast<_U_diff>(_Idx) < static_cast<_U_diff>(_RANGES size(_Self)), + "index out of range for view_interface"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _RANGES begin(_Self)[_Idx]; @@ -3595,7 +3614,9 @@ namespace ranges { auto& _Self = _Cast(); #if _CONTAINER_DEBUG_LEVEL > 0 if constexpr (sized_range<_Derived>) { - _STL_VERIFY(_Idx < _RANGES size(_Self), "index out of range for view_interface"); + using _U_diff = _Make_unsigned_like_t>; + _STL_VERIFY(static_cast<_U_diff>(_Idx) < static_cast<_U_diff>(_RANGES size(_Self)), + "index out of range for view_interface"); } #endif // _CONTAINER_DEBUG_LEVEL > 0 return _RANGES begin(_Self)[_Idx]; diff --git a/tests/std/include/range_algorithm_support.hpp b/tests/std/include/range_algorithm_support.hpp index 60fa690bc52..055ef4cb0a7 100644 --- a/tests/std/include/range_algorithm_support.hpp +++ b/tests/std/include/range_algorithm_support.hpp @@ -573,6 +573,93 @@ struct std::pointer_traits<::test::iterator + class range_base { + public: + static_assert(Copy == Copyability::immobile); + + range_base() = default; + constexpr explicit range_base(span elements) noexcept : elements_{elements} {} + + range_base(const range_base&) = delete; + range_base& operator=(const range_base&) = delete; + + protected: + [[nodiscard]] constexpr bool moved_from() const noexcept { + return false; + } + span elements_; + }; + + template + class range_base { + public: + range_base() = default; + constexpr explicit range_base(span elements) noexcept : elements_{elements} {} + + constexpr range_base(range_base&& that) noexcept + : elements_{that.elements_}, moved_from_{that.moved_from_} { + that.elements_ = {}; + that.moved_from_ = true; + } + + constexpr range_base& operator=(range_base&& that) noexcept { + elements_ = that.elements_; + moved_from_ = that.moved_from_; + that.elements_ = {}; + that.moved_from_ = true; + return *this; + } + + protected: + [[nodiscard]] constexpr bool moved_from() const noexcept { + return moved_from_; + } + + span elements_; + + private: + bool moved_from_ = false; + }; + + template + class range_base { + public: + range_base() = default; + constexpr explicit range_base(span elements) noexcept : elements_{elements} {} + + range_base(const range_base&) = default; + range_base& operator=(const range_base&) = default; + + constexpr range_base(range_base&& that) noexcept + : elements_{that.elements_}, moved_from_{that.moved_from_} { + that.elements_ = {}; + that.moved_from_ = true; + } + + constexpr range_base& operator=(range_base&& that) noexcept { + elements_ = that.elements_; + moved_from_ = that.moved_from_; + that.elements_ = {}; + that.moved_from_ = true; + return *this; + } + + protected: + [[nodiscard]] constexpr bool moved_from() const noexcept { + return moved_from_; + } + + span elements_; + + private: + bool moved_from_ = false; + }; + } // namespace detail // clang-format off template }, // Use a ProxyRef reference type? - ProxyRef Proxy = ProxyRef{!derived_from}> + ProxyRef Proxy = ProxyRef{!derived_from}, + // Should this range satisfy the view concept? + CanView IsView = CanView::no, + // Should this range type be copyable/movable/neither? + Copyability Copy = IsView == CanView::yes ? Copyability::move_only : Copyability::immobile> requires (!to_bool(IsCommon) || to_bool(Eq)) && (to_bool(Eq) || !derived_from) && (!to_bool(Proxy) || !derived_from) - class range { - span elements_; + && (!to_bool(IsView) || Copy != Copyability::immobile) + class range : public detail::range_base { + private: mutable bool begin_called_ = false; + using detail::range_base::elements_; + + using detail::range_base::moved_from; public: using I = iterator; using S = conditional_t>; - range() = default; - constexpr explicit range(span elements) noexcept : elements_{elements} {} - - range(range const&) = delete; - range& operator=(range const&) = delete; + using detail::range_base::range_base; [[nodiscard]] constexpr I begin() const noexcept { + assert(!moved_from()); if constexpr (!derived_from) { assert(!exchange(begin_called_, true)); } @@ -611,10 +703,12 @@ namespace test { } [[nodiscard]] constexpr S end() const noexcept { + assert(!moved_from()); return S{elements_.data() + elements_.size()}; } [[nodiscard]] constexpr ptrdiff_t size() const noexcept requires (to_bool(IsSized)) { + assert(!moved_from()); if constexpr (!derived_from) { assert(!begin_called_); } @@ -622,6 +716,7 @@ namespace test { } [[nodiscard]] constexpr Element* data() const noexcept requires derived_from { + assert(!moved_from()); return elements_.data(); } @@ -629,12 +724,14 @@ namespace test { using US = conditional_t>; [[nodiscard]] constexpr UI _Unchecked_begin() const noexcept { + assert(!moved_from()); if constexpr (!derived_from) { assert(!exchange(begin_called_, true)); } return UI{elements_.data()}; } [[nodiscard]] constexpr US _Unchecked_end() const noexcept { + assert(!moved_from()); return US{elements_.data() + elements_.size()}; } @@ -649,6 +746,11 @@ namespace test { // clang-format on } // namespace test +template +inline constexpr bool std::ranges::enable_view< + test::range> = true; + template class basic_borrowed_range : public test::range { @@ -1170,3 +1272,110 @@ struct get_nth_fn { }; inline constexpr get_nth_fn<0> get_first; inline constexpr get_nth_fn<1> get_second; + +template +concept CanBegin = requires(R&& r) { + ranges::begin(std::forward(r)); +}; +template +concept CanMemberBegin = requires(R&& r) { + std::forward(r).begin(); +}; + +template +concept CanEnd = requires(R&& r) { + ranges::end(std::forward(r)); +}; +template +concept CanMemberEnd = requires(R&& r) { + std::forward(r).end(); +}; + +template +concept CanCBegin = requires(R&& r) { + ranges::cbegin(std::forward(r)); +}; +template +concept CanCEnd = requires(R&& r) { + ranges::cend(std::forward(r)); +}; + +template +concept CanRBegin = requires(R&& r) { + ranges::rbegin(std::forward(r)); +}; +template +concept CanREnd = requires(R&& r) { + ranges::rend(std::forward(r)); +}; + +template +concept CanCRBegin = requires(R&& r) { + ranges::crbegin(std::forward(r)); +}; +template +concept CanCREnd = requires(R&& r) { + ranges::crend(std::forward(r)); +}; + +template +concept CanEmpty = requires(R&& r) { + ranges::empty(std::forward(r)); +}; + +template +concept CanSize = requires(R&& r) { + ranges::size(std::forward(r)); +}; +template +concept CanMemberSize = requires(R&& r) { + std::forward(r).size(); +}; + +template +concept CanSSize = requires(R&& r) { + ranges::ssize(std::forward(r)); +}; + +template +concept CanData = requires(R&& r) { + ranges::data(std::forward(r)); +}; +template +concept CanMemberData = requires(R&& r) { + std::forward(r).data(); +}; + +template +concept CanCData = requires(R&& r) { + ranges::cdata(std::forward(r)); +}; + +template +concept CanMemberBase = requires(T&& t) { + std::forward(t).base(); +}; + +template +concept CanMemberEmpty = requires(R&& r) { + std::forward(r).empty(); +}; + +template +concept CanMemberFront = requires(R&& r) { + std::forward(r).front(); +}; +template +concept CanMemberBack = requires(R&& r) { + std::forward(r).back(); +}; + +template +concept CanIndex = requires(R&& r, const ranges::range_difference_t i) { + std::forward(r)[i]; +}; + +template +concept CanBool = requires(R&& r) { + std::forward(r) ? true : false; +}; diff --git a/tests/std/test.lst b/tests/std/test.lst index 499a40f9004..713c8d541e9 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -317,7 +317,9 @@ tests\P0896R4_ranges_ref_view tests\P0896R4_ranges_subrange tests\P0896R4_ranges_test_machinery tests\P0896R4_ranges_to_address +tests\P0896R4_views_all tests\P0896R4_views_empty +tests\P0896R4_views_reverse tests\P0896R4_views_single tests\P0898R3_concepts tests\P0898R3_identity diff --git a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp index 5289201f181..c8d3518b70b 100644 --- a/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_range_machinery/test.cpp @@ -34,45 +34,10 @@ STATIC_ASSERT(std::same_as, std::size_t>); template concept Decayed = std::same_as, T>; -// clang-format off template -concept CanBegin = requires(R&& r) { ranges::begin(std::forward(r)); }; -template -concept CanEnd = requires(R&& r) { ranges::end(std::forward(r)); }; - -template -concept CanCBegin = requires(R&& r) { ranges::cbegin(std::forward(r)); }; -template -concept CanCEnd = requires(R&& r) {ranges::cend(std::forward(r)); }; - -template -concept CanRBegin = requires(R&& r) { ranges::rbegin(std::forward(r)); }; -template -concept CanREnd = requires(R&& r) { ranges::rend(std::forward(r)); }; - -template -concept CanCRBegin = requires(R&& r) { ranges::crbegin(std::forward(r)); }; -template -concept CanCREnd = requires(R&& r) { ranges::crend(std::forward(r)); }; - -template -concept CanEmpty = requires(R&& r) { ranges::empty(std::forward(r)); }; - -template -concept CanSize = requires(R&& r) { ranges::size(std::forward(r)); }; - -template -concept CanSSize = requires(R&& r) { ranges::ssize(std::forward(r)); }; - -template -concept CanSizeType = requires { typename ranges::range_size_t; }; - -template -concept CanData = requires(R&& r) { ranges::data(std::forward(r)); }; - -template -concept CanCData = requires(R&& r) { ranges::cdata(std::forward(r)); }; -// clang-format on +concept CanSizeType = requires { + typename ranges::range_size_t; +}; struct invalid_type {}; @@ -124,6 +89,8 @@ STATIC_ASSERT(test_cpo(ranges::empty)); STATIC_ASSERT(test_cpo(ranges::data)); STATIC_ASSERT(test_cpo(ranges::cdata)); +STATIC_ASSERT(test_cpo(ranges::views::all)); +STATIC_ASSERT(test_cpo(ranges::views::reverse)); STATIC_ASSERT(test_cpo(ranges::views::single)); void test_cpo_ambiguity() { diff --git a/tests/std/tests/P0896R4_ranges_subrange/test.cpp b/tests/std/tests/P0896R4_ranges_subrange/test.cpp index 961505a64ce..d3e67fbcc01 100644 --- a/tests/std/tests/P0896R4_ranges_subrange/test.cpp +++ b/tests/std/tests/P0896R4_ranges_subrange/test.cpp @@ -62,35 +62,6 @@ namespace test_view_interface { STATIC_ASSERT(test_template_id()); STATIC_ASSERT(test_template_id()); - template - concept CanEmpty = requires(T& t) { - ranges::empty(t); - }; - template - concept CanBool = requires(T& t) { - static_cast(t); - }; - template - concept CanData = requires(T& t) { - ranges::data(t); - }; - template - concept CanSize = requires(T& t) { - ranges::size(t); - }; - template - concept CanFront = requires(T& t) { - t.front(); - }; - template - concept CanBack = requires(T& t) { - t.back(); - }; - template - concept CanIndex = requires(T& t) { - t[42]; - }; - using test::CanCompare, test::CanDifference, test::Common, test::ProxyRef, test::to_bool; enum class ConstRange : bool { no, yes }; @@ -113,20 +84,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace output_unsized_onlymutable namespace output_unsized_allowconst { @@ -134,20 +105,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace output_unsized_allowconst namespace output_sized_onlymutable { @@ -155,20 +126,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace output_sized_onlymutable namespace output_sized_allowconst { @@ -176,20 +147,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace output_sized_allowconst namespace input_unsized_onlymutable { @@ -197,20 +168,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace input_unsized_onlymutable namespace input_unsized_allowconst { @@ -218,20 +189,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace input_unsized_allowconst namespace input_sized_onlymutable { @@ -239,20 +210,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace input_sized_onlymutable namespace input_sized_allowconst { @@ -260,20 +231,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace input_sized_allowconst namespace forward_uncommon_unsized_onlymutable { @@ -281,20 +252,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_uncommon_unsized_onlymutable namespace forward_uncommon_unsized_allowconst { @@ -302,20 +273,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_uncommon_unsized_allowconst namespace forward_uncommon_sized_onlymutable { @@ -323,20 +294,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_uncommon_sized_onlymutable namespace forward_uncommon_sized_allowconst { @@ -344,20 +315,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_uncommon_sized_allowconst namespace forward_common_unsized_onlymutable { @@ -365,20 +336,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_common_unsized_onlymutable namespace forward_common_unsized_allowconst { @@ -386,20 +357,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_common_unsized_allowconst namespace forward_common_sized_onlymutable { @@ -407,20 +378,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_common_sized_onlymutable namespace forward_common_sized_allowconst { @@ -428,20 +399,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace forward_common_sized_allowconst namespace bidi_uncommon_unsized_onlymutable { @@ -449,20 +420,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_uncommon_unsized_onlymutable namespace bidi_uncommon_unsized_allowconst { @@ -470,20 +441,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_uncommon_unsized_allowconst namespace bidi_uncommon_sized_onlymutable { @@ -491,20 +462,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_uncommon_sized_onlymutable namespace bidi_uncommon_sized_allowconst { @@ -512,20 +483,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_uncommon_sized_allowconst namespace bidi_common_unsized_onlymutable { @@ -533,20 +504,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_common_unsized_onlymutable namespace bidi_common_unsized_allowconst { @@ -554,20 +525,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_common_unsized_allowconst namespace bidi_common_sized_onlymutable { @@ -575,20 +546,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_common_sized_onlymutable namespace bidi_common_sized_allowconst { @@ -596,20 +567,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(!CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace bidi_common_sized_allowconst namespace random_uncommon_sized_onlymutable { @@ -617,20 +588,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace random_uncommon_sized_onlymutable namespace random_uncommon_sized_allowconst { @@ -638,20 +609,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanIndex); } // namespace random_uncommon_sized_allowconst namespace random_common_sized_onlymutable { @@ -659,20 +630,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace random_common_sized_onlymutable namespace random_common_sized_allowconst { @@ -680,20 +651,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanIndex); } // namespace random_common_sized_allowconst namespace contiguous_uncommon_sized_onlymutable { @@ -701,20 +672,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace contiguous_uncommon_sized_onlymutable namespace contiguous_uncommon_sized_allowconst { @@ -722,20 +693,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanData); - STATIC_ASSERT(CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanData); + STATIC_ASSERT(CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanIndex); } // namespace contiguous_uncommon_sized_allowconst namespace contiguous_common_sized_onlymutable { @@ -743,20 +714,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(!ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(!CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(!CanBool); - STATIC_ASSERT(CanData); - STATIC_ASSERT(!CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(!CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(!CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(!CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(!CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(!CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(!CanBool); + STATIC_ASSERT(CanData); + STATIC_ASSERT(!CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(!CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(!CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(!CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(!CanIndex); } // namespace contiguous_common_sized_onlymutable namespace contiguous_common_sized_allowconst { @@ -764,20 +735,20 @@ namespace test_view_interface { STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::range); STATIC_ASSERT(ranges::view); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanEmpty); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanBool); - STATIC_ASSERT(CanData); - STATIC_ASSERT(CanData); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanSize); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanFront); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(CanBack); - STATIC_ASSERT(CanIndex); - STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanEmpty); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanBool); + STATIC_ASSERT(CanData); + STATIC_ASSERT(CanData); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanSize); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberFront); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(CanMemberBack); + STATIC_ASSERT(CanIndex); + STATIC_ASSERT(CanIndex); } // namespace contiguous_common_sized_allowconst } // namespace test_view_interface diff --git a/tests/std/tests/P0896R4_views_all/env.lst b/tests/std/tests/P0896R4_views_all/env.lst new file mode 100644 index 00000000000..f3ccc8613c6 --- /dev/null +++ b/tests/std/tests/P0896R4_views_all/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\concepts_matrix.lst diff --git a/tests/std/tests/P0896R4_views_all/test.cpp b/tests/std/tests/P0896R4_views_all/test.cpp new file mode 100644 index 00000000000..b44020a9344 --- /dev/null +++ b/tests/std/tests/P0896R4_views_all/test.cpp @@ -0,0 +1,218 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +using namespace std; + +template +concept CanViewAll = requires(Rng&& r) { + views::all(static_cast(r)); +}; + +// Test a silly precomposed range adaptor pipeline +constexpr auto pipeline = views::all | views::all | views::all | views::all | views::all | views::all; + +template +constexpr bool test_one(Rng&& rng) { + constexpr bool is_view = ranges::view>; + static_assert(is_view || is_lvalue_reference_v); + + using V = conditional_t, ranges::ref_view>>; + + static_assert(CanViewAll == (!is_view || copyable) ); + if constexpr (!is_view || copyable) { // Validate lvalue + constexpr bool is_noexcept = !is_view || is_nothrow_copy_constructible_v; + + static_assert(same_as, V>); + static_assert(same_as); + static_assert(noexcept(views::all(rng)) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(rng | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(rng | views::all | views::all | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(rng | pipeline) == is_noexcept); + } + + static_assert(CanViewAll&> == (!is_view || copyable) ); + if constexpr (is_view && copyable) { + constexpr bool is_noexcept = is_nothrow_copy_constructible_v; + + static_assert(same_as&>, V>); + static_assert(same_as); + static_assert(noexcept(views::all(as_const(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::all | views::all | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | pipeline) == is_noexcept); + } else if constexpr (!is_view) { + using RV = ranges::ref_view>; + + static_assert(same_as&>, RV>); + static_assert(same_as); + static_assert(noexcept(views::all(as_const(rng)))); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::all)); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::all | views::all | views::all)); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | pipeline)); + } + + // Validate rvalue + static_assert(CanViewAll> == is_view || ranges::enable_borrowed_range>); + if constexpr (is_view) { + constexpr bool is_noexcept = is_nothrow_move_constructible_v; + static_assert(same_as>, V>); + static_assert(same_as); + static_assert(noexcept(views::all(move(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::all | views::all | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | pipeline) == is_noexcept); + } else if constexpr (ranges::enable_borrowed_range) { + using S = decltype(ranges::subrange{declval()}); + constexpr bool is_noexcept = noexcept(S{declval()}); + + static_assert(same_as>, S>); + static_assert(same_as); + static_assert(noexcept(views::all(move(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::all | views::all | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | pipeline) == is_noexcept); + } + + // Validate const rvalue + static_assert(CanViewAll> == (is_view && copyable) + || (!is_view && ranges::enable_borrowed_range>) ); + if constexpr (is_view && copyable) { + constexpr bool is_noexcept = is_nothrow_copy_constructible_v; + + static_assert(same_as>, V>); + static_assert(same_as); + static_assert(noexcept(views::all(as_const(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | views::all | views::all | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | pipeline) == is_noexcept); + } else if constexpr (!is_view && ranges::enable_borrowed_range>) { + using S = decltype(ranges::subrange{declval>()}); + constexpr bool is_noexcept = noexcept(S{declval>()}); + + static_assert(same_as>, S>); + static_assert(same_as); + static_assert(noexcept(views::all(move(as_const(rng)))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | views::all | views::all | views::all) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | pipeline) == is_noexcept); + } + + return true; +} + +struct non_view_borrowed_range { + int* begin() const; + int* end() const; +}; + +template <> +inline constexpr bool ranges::enable_borrowed_range = true; + +template > +using move_only_view = test::range}, + test::ProxyRef{!derived_from}, test::CanView::yes, test::Copyability::move_only>; + +int main() { + static constexpr int some_ints[] = {0, 1, 2}; + + // Validate views + { // ... copyable + constexpr string_view str{"Hello, World!"}; + static_assert(test_one(str)); + test_one(str); + assert(ranges::equal(views::all(str), str)); + } + { // ... move-only + test_one(move_only_view{some_ints}); + assert(ranges::equal(views::all(move_only_view{some_ints}), some_ints)); + test_one(move_only_view{some_ints}); + assert(ranges::equal(views::all(move_only_view{some_ints}), some_ints)); + test_one(move_only_view{some_ints}); + assert( + ranges::equal(views::all(move_only_view{some_ints}), some_ints)); + test_one(move_only_view{some_ints}); + assert(ranges::equal( + views::all(move_only_view{some_ints}), some_ints)); + test_one(move_only_view{some_ints}); + assert(ranges::equal( + views::all(move_only_view{some_ints}), some_ints)); + test_one(move_only_view{some_ints}); + assert(ranges::equal( + views::all(move_only_view{some_ints}), some_ints)); + test_one(move_only_view{some_ints}); + assert(ranges::equal( + views::all(move_only_view{some_ints}), some_ints)); + } + + // Validate non-views + { + static_assert(test_one(some_ints)); + test_one(some_ints); + assert(ranges::equal(views::all(some_ints), some_ints)); + } + { + string str{"Hello, World!"}; + test_one(str); + assert(ranges::equal(views::all(str), str)); + } + + // Validate a non-view borrowed range + { + constexpr span s{some_ints}; + static_assert(test_one(s)); + test_one(s); + } +} diff --git a/tests/std/tests/P0896R4_views_reverse/env.lst b/tests/std/tests/P0896R4_views_reverse/env.lst new file mode 100644 index 00000000000..62a24024479 --- /dev/null +++ b/tests/std/tests/P0896R4_views_reverse/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\strict_concepts_matrix.lst diff --git a/tests/std/tests/P0896R4_views_reverse/test.cpp b/tests/std/tests/P0896R4_views_reverse/test.cpp new file mode 100644 index 00000000000..c21a1f5bed2 --- /dev/null +++ b/tests/std/tests/P0896R4_views_reverse/test.cpp @@ -0,0 +1,375 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +using namespace std; + +template +concept CanViewReverse = requires(Rng&& r) { + views::reverse(static_cast(r)); +}; + +// Test a silly precomposed range adaptor pipeline +constexpr auto pipeline = views::all | views::reverse | views::all | views::reverse | views::all | views::reverse; + +template +constexpr bool test_one(Rng&& rng, Expected&& expected) { + using ranges::common_range, ranges::reverse_view, ranges::sized_range, ranges::begin, ranges::end, ranges::size, + ranges::iterator_t, ranges::range_size_t, ranges::random_access_range, ranges::prev, + ranges::enable_borrowed_range; + constexpr bool is_view = ranges::view>; + + using V = views::all_t; + using R = reverse_view; + static_assert(ranges::view); + static_assert(ranges::bidirectional_range); + static_assert(random_access_range == random_access_range); + static_assert(!ranges::contiguous_range); + + // Validate range adapter object + // ...with lvalue argument + static_assert(CanViewReverse == (!is_view || copyable) ); + if constexpr (CanViewReverse) { + constexpr bool is_noexcept = !is_view || is_nothrow_copy_constructible_v; + + static_assert(same_as); + static_assert(noexcept(views::reverse(rng)) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(rng | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(views::reverse(views::reverse(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(rng | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(rng | pipeline) == is_noexcept); + } + + // ... with const lvalue argument + static_assert(CanViewReverse&> == (!is_view || copyable) ); + if constexpr (is_view && copyable) { + constexpr bool is_noexcept = is_nothrow_copy_constructible_v; + + static_assert(same_as); + static_assert(noexcept(views::reverse(as_const(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | pipeline) == is_noexcept); + } else if constexpr (!is_view) { + using RC = reverse_view&>>; + constexpr bool is_noexcept = is_nothrow_constructible_v&>; + + static_assert(same_as); + static_assert(noexcept(views::reverse(as_const(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | pipeline) == is_noexcept); + } + + // ... with rvalue argument + static_assert(CanViewReverse> == is_view || enable_borrowed_range>); + if constexpr (is_view) { + constexpr bool is_noexcept = is_nothrow_move_constructible_v; + static_assert(same_as); + static_assert(noexcept(views::reverse(move(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | pipeline) == is_noexcept); + } else if constexpr (enable_borrowed_range) { + using S = decltype(ranges::subrange{declval()}); + using RS = reverse_view; + constexpr bool is_noexcept = noexcept(S{declval()}); + + static_assert(same_as); + static_assert(noexcept(views::reverse(move(rng))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(rng) | pipeline) == is_noexcept); + } + + // ... with const rvalue argument + static_assert(CanViewReverse> == (is_view && copyable) + || (!is_view && enable_borrowed_range>) ); + if constexpr (is_view && copyable) { + constexpr bool is_noexcept = is_nothrow_copy_constructible_v; + + static_assert(same_as); + static_assert(noexcept(views::reverse(as_const(rng))) == is_nothrow_copy_constructible_v); + + static_assert(same_as); + static_assert(noexcept(as_const(rng) | views::reverse) == is_nothrow_copy_constructible_v); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | pipeline) == is_noexcept); + } else if constexpr (!is_view && enable_borrowed_range>) { + using S = decltype(ranges::subrange{declval>()}); + using RS = reverse_view; + constexpr bool is_noexcept = noexcept(S{declval>()}); + + static_assert(same_as); + static_assert(noexcept(views::reverse(move(as_const(rng)))) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | views::reverse | views::reverse | views::reverse) == is_noexcept); + + static_assert(same_as); + static_assert(noexcept(move(as_const(rng)) | pipeline) == is_noexcept); + } + + // Validate deduction guide +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, DevCom-1159442 + (void) 42; +#endif // TRANSITION, DevCom-1159442 + same_as auto r = reverse_view{forward(rng)}; + assert(ranges::equal(r, expected)); + + // Validate reverse_view::size + static_assert(CanMemberSize == sized_range); + if constexpr (sized_range) { + assert(r.size() == static_cast>(size(expected))); + static_assert(noexcept(r.size()) == noexcept(size(rng))); + } + + static_assert(CanMemberSize == sized_range); + if constexpr (sized_range) { + assert(as_const(r).size() == static_cast>(size(expected))); + static_assert(noexcept(r.size()) == noexcept(size(as_const(rng)))); + } + + // Validate view_interface::empty and operator bool + const bool is_empty = ranges::empty(expected); + assert(r.empty() == is_empty); + assert(static_cast(r) == !is_empty); + static_assert(CanMemberEmpty == common_range); + if constexpr (common_range) { + assert(as_const(r).empty() == is_empty); + assert(static_cast(as_const(r)) == !is_empty); + } + + // Validate reverse_view::begin + static_assert(CanMemberBegin); + { + // reverse_view sometimes caches begin, so let's make several extra calls + const same_as>> auto i = r.begin(); + if (!is_empty) { + assert(*i == *begin(expected)); + } + assert(r.begin() == i); + assert(r.begin() == i); + // NB: non-const begin is unconditionally noexcept(false) due to caching + static_assert(!noexcept(r.begin())); + + if constexpr (copyable) { + auto r2 = r; + const same_as>> auto i2 = r2.begin(); + assert(r2.begin() == i2); + assert(r2.begin() == i2); + if (!is_empty) { + assert(*i2 == *i); + } + } + + static_assert(CanMemberBegin == common_range); + if constexpr (common_range) { + const same_as>> auto ci = as_const(r).begin(); + assert(as_const(r).begin() == ci); + assert(as_const(r).begin() == ci); + if (!is_empty) { + assert(*ci == *i); + } + static_assert(noexcept(as_const(r).begin()) == noexcept(reverse_iterator{end(as_const(rng))})); + + if constexpr (copyable) { + const auto r2 = r; + const same_as>> auto ci2 = r2.begin(); + assert(r2.begin() == ci2); + assert(r2.begin() == ci2); + if (!is_empty) { + assert(*ci2 == *i); + } + } + } + } + + // Validate reverse_view::end + static_assert(CanMemberEnd); + if (!is_empty) { + assert(*prev(r.end()) == *prev(end(expected))); + + if constexpr (copyable) { + auto r2 = r; + assert(*prev(r2.end()) == *prev(end(expected))); + } + static_assert(noexcept(r.end()) == noexcept(reverse_iterator{begin(rng)})); + + static_assert(CanMemberEnd == common_range); + if constexpr (common_range) { + assert(*prev(as_const(r).end()) == *prev(end(expected))); + static_assert(noexcept(as_const(r).end()) == noexcept(reverse_iterator{begin(as_const(rng))})); + } + } + + // Validate view_interface::data + static_assert(!CanData); + static_assert(!CanData); + + if (!is_empty) { + // Validate view_interface::operator[] + static_assert(CanIndex == random_access_range); + static_assert(CanIndex == (random_access_range && common_range) ); + if constexpr (random_access_range) { + assert(r[0] == *begin(expected)); + + if constexpr (common_range) { + assert(as_const(r)[0] == *begin(expected)); + } + } + + // Validate view_interface::front and back + assert(r.front() == *begin(expected)); + assert(r.back() == *prev(end(expected))); + + static_assert(CanMemberFront == common_range); + static_assert(CanMemberBack == common_range); + if constexpr (common_range) { + assert(as_const(r).front() == *begin(expected)); + assert(as_const(r).back() == *prev(end(expected))); + } + } + + // Validate reverse_view::base() const& + static_assert(CanMemberBase == copy_constructible); + if constexpr (copy_constructible) { + same_as auto b1 = as_const(r).base(); + static_assert(noexcept(as_const(r).base()) == is_nothrow_copy_constructible_v); + if (!is_empty) { + assert(*b1.begin() == *prev(end(expected))); + if constexpr (common_range) { + assert(*prev(b1.end()) == *begin(expected)); + } + } + } + + // Validate reverse_view::base() && (NB: do this last since it leaves r moved-from) +#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, DevCom-1159442 + (void) 42; +#endif // TRANSITION, DevCom-1159442 + same_as auto b2 = move(r).base(); + static_assert(noexcept(move(r).base()) == is_nothrow_move_constructible_v); + if (!is_empty) { + assert(*b2.begin() == *prev(end(expected))); + if constexpr (common_range) { + assert(*prev(b2.end()) == *begin(expected)); + } + } + + return true; +} + +struct instantiator { + template + static constexpr void call() { + R r{}; + test_one(r, span{}); + } +}; + +template > +using move_only_view = test::range}, + test::ProxyRef{!derived_from}, test::CanView::yes, test::Copyability::move_only>; + +int main() { + static constexpr int some_ints[] = {0, 1, 2}; + static constexpr int reversed_ints[] = {2, 1, 0}; + + // Validate views + { // ...copyable + constexpr string_view str{"Hello, World!"}; + constexpr auto expected = "!dlroW ,olleH"sv; + static_assert(test_one(str, expected)); + test_one(str, expected); + } + { // ... move-only + test_one(move_only_view{some_ints}, reversed_ints); + test_one(move_only_view{some_ints}, reversed_ints); + test_one(move_only_view{some_ints}, reversed_ints); + test_one(move_only_view{some_ints}, reversed_ints); + test_one(move_only_view{some_ints}, reversed_ints); + test_one(move_only_view{some_ints}, reversed_ints); + } + + // Validate non-views + { // ... C array + static_assert(test_one(some_ints, reversed_ints)); + test_one(some_ints, reversed_ints); + } + { // ... contiguous container + string str{"Hello, World!"}; + constexpr auto expected = "!dlroW ,olleH"sv; + test_one(str, expected); + } + { // ... bidi container + list lst{3, 4, 5}; + static constexpr int reversed[] = {5, 4, 3}; + test_one(lst, reversed); + + static constexpr int reversed_prefix[] = {4, 3}; + assert(ranges::equal( + views::reverse(ranges::subrange{counted_iterator{lst.begin(), 2}, default_sentinel}), reversed_prefix)); + } + + // Validate a non-view borrowed range + { + constexpr span s{some_ints}; + static_assert(test_one(s, reversed_ints)); + test_one(s, reversed_ints); + } + + // Get full instantiation coverage + static_assert((test_bidi(), true)); + test_bidi(); +}