diff --git a/stl/inc/iterator b/stl/inc/iterator index 195a8dd61b0..08814af493b 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -32,9 +32,7 @@ public: #ifdef __cpp_lib_concepts using difference_type = ptrdiff_t; - - constexpr back_insert_iterator() noexcept = default; -#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv +#else using difference_type = void; #endif // __cpp_lib_concepts @@ -64,7 +62,7 @@ public: } protected: - _Container* container = nullptr; + _Container* container; }; // FUNCTION TEMPLATE back_inserter @@ -87,9 +85,7 @@ public: #ifdef __cpp_lib_concepts using difference_type = ptrdiff_t; - - constexpr front_insert_iterator() noexcept = default; -#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv +#else using difference_type = void; #endif // __cpp_lib_concepts @@ -119,7 +115,7 @@ public: } protected: - _Container* container = nullptr; + _Container* container; }; // FUNCTION TEMPLATE front_inserter @@ -138,17 +134,16 @@ public: using reference = void; using container_type = _Container; - #ifdef __cpp_lib_concepts using difference_type = ptrdiff_t; - - insert_iterator() = default; -#else // ^^^ __cpp_lib_concepts / !__cpp_lib_concepts vvv + using _Wrapped_iter = ranges::iterator_t<_Container>; +#else // ^^^ implementing Ranges // no Ranges vvv using difference_type = void; + using _Wrapped_iter = typename _Container::iterator; #endif // __cpp_lib_concepts - _CONSTEXPR20 insert_iterator(_Container& _Cont, typename _Container::iterator _Where) - : container(_STD addressof(_Cont)), iter(_Where) {} + _CONSTEXPR20 insert_iterator(_Container& _Cont, _Wrapped_iter _Where) + : container(_STD addressof(_Cont)), iter(_STD move(_Where)) {} _CONSTEXPR20 insert_iterator& operator=(const typename _Container::value_type& _Val) { // insert into container and increment stored iterator @@ -176,8 +171,8 @@ public: } protected: - _Container* container = nullptr; - typename _Container::iterator iter{}; + _Container* container; + _Wrapped_iter iter; }; // FUNCTION TEMPLATE inserter @@ -327,10 +322,6 @@ public: using traits_type = _Traits; using ostream_type = basic_ostream<_Elem, _Traits>; -#ifdef __cpp_lib_concepts - constexpr ostream_iterator() noexcept = default; -#endif // __cpp_lib_concepts - ostream_iterator(ostream_type& _Ostr, const _Elem* const _Delim = nullptr) noexcept /* strengthened */ : _Mydelim(_Delim), _Myostr(_STD addressof(_Ostr)) {} @@ -356,8 +347,8 @@ public: } private: - const _Elem* _Mydelim = nullptr; // pointer to delimiter string (NB: not freed) - ostream_type* _Myostr = nullptr; // pointer to output stream + const _Elem* _Mydelim; // pointer to delimiter string (NB: not freed) + ostream_type* _Myostr; // pointer to output stream }; // CLASS TEMPLATE istreambuf_iterator @@ -516,10 +507,6 @@ public: using streambuf_type = basic_streambuf<_Elem, _Traits>; using ostream_type = basic_ostream<_Elem, _Traits>; -#ifdef __cpp_lib_concepts - constexpr ostreambuf_iterator() noexcept = default; -#endif // __cpp_lib_concepts - ostreambuf_iterator(streambuf_type* _Sb) noexcept : _Strbuf(_Sb) {} ostreambuf_iterator(ostream_type& _Ostr) noexcept : _Strbuf(_Ostr.rdbuf()) {} @@ -549,8 +536,8 @@ public: } private: - bool _Failed = false; // true if any stores have failed - streambuf_type* _Strbuf = nullptr; + bool _Failed = false; // true if any stores have failed + streambuf_type* _Strbuf; }; #ifdef __cpp_lib_concepts @@ -566,7 +553,7 @@ class _Variantish { public: constexpr explicit _Variantish(_Common_iterator_construct_tag) noexcept : _Contains{_Variantish_state::_Nothing} {} - constexpr _Variantish() noexcept(is_nothrow_default_constructible_v<_It>) + constexpr _Variantish() noexcept(is_nothrow_default_constructible_v<_It>) requires default_initializable<_It> : _Iterator{}, _Contains{_Variantish_state::_Holds_iter} {} template @@ -849,7 +836,7 @@ private: }; public: - constexpr common_iterator() = default; + constexpr common_iterator() requires default_initializable<_Iter> = default; constexpr common_iterator(_Iter _Right) noexcept(is_nothrow_move_constructible_v<_Iter>) // strengthened : _Val{in_place_type<_Iter>, _STD move(_Right)} {} @@ -1057,7 +1044,7 @@ public: using iterator_type = _Iter; // [counted.iter.const] - constexpr counted_iterator() = default; + constexpr counted_iterator() requires default_initializable<_Iter> = default; constexpr counted_iterator(_Iter _Right, const iter_difference_t<_Iter> _Diff) noexcept( is_nothrow_move_constructible_v<_Iter>) // strengthened : _Current(_STD move(_Right)), _Length(_Diff) { diff --git a/stl/inc/ranges b/stl/inc/ranges index 33e15b978c8..d67f6582204 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -242,48 +242,47 @@ namespace ranges { template using _Cached_position_t = conditional_t<_Enable, _Cached_position<_Rng, _Derived>, view_interface<_Derived>>; - // CLASS TEMPLATE ranges::_Semiregular_box + // CLASS TEMPLATE ranges::_Copyable_box template <_Copy_constructible_object _Ty> - class _Semiregular_box { + class _Copyable_box { // a simplified optional that augments copy_constructible types with full copyability public: - constexpr _Semiregular_box() noexcept : _Dummy{}, _Engaged{false} {} - constexpr _Semiregular_box() noexcept( - is_nothrow_default_constructible_v<_Ty>) requires default_initializable<_Ty> + constexpr _Copyable_box() noexcept(is_nothrow_default_constructible_v<_Ty>) requires default_initializable<_Ty> : _Val(), _Engaged{true} {} template - constexpr _Semiregular_box(in_place_t, _Types&&... _Args) noexcept( + constexpr _Copyable_box(in_place_t, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _Val(_STD forward<_Types>(_Args)...), _Engaged{true} {} - ~_Semiregular_box() requires is_trivially_destructible_v<_Ty> = default; + ~_Copyable_box() requires is_trivially_destructible_v<_Ty> = default; - ~_Semiregular_box() { + _CONSTEXPR20_DYNALLOC ~_Copyable_box() { if (_Engaged) { _Val.~_Ty(); } } - _Semiregular_box(const _Semiregular_box&) requires is_trivially_copy_constructible_v<_Ty> = default; - _Semiregular_box(const _Semiregular_box& _That) : _Engaged{_That._Engaged} { + _Copyable_box(const _Copyable_box&) requires is_trivially_copy_constructible_v<_Ty> = default; + _CONSTEXPR20_DYNALLOC _Copyable_box(const _Copyable_box& _That) : _Engaged{_That._Engaged} { if (_That._Engaged) { _Construct_in_place(_Val, _That._Val); } } - _Semiregular_box(_Semiregular_box&&) requires is_trivially_move_constructible_v<_Ty> = default; - _Semiregular_box(_Semiregular_box&& _That) : _Engaged{_That._Engaged} { + _Copyable_box(_Copyable_box&&) requires is_trivially_move_constructible_v<_Ty> = default; + _CONSTEXPR20_DYNALLOC _Copyable_box(_Copyable_box&& _That) : _Engaged{_That._Engaged} { if (_That._Engaged) { _Construct_in_place(_Val, _STD move(_That._Val)); } } // clang-format off - _Semiregular_box& operator=(const _Semiregular_box&) noexcept + _Copyable_box& operator=(const _Copyable_box&) noexcept requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default; // clang-format on - _Semiregular_box& operator=(const _Semiregular_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>&& + _CONSTEXPR20_DYNALLOC _Copyable_box& operator=(const _Copyable_box& _That) noexcept( + is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_copy_assignable_v<_Ty>) /* strengthened */ requires copyable<_Ty> { if (_Engaged) { if (_That._Engaged) { @@ -304,28 +303,32 @@ namespace ranges { return *this; } - _Semiregular_box& operator=(const _Semiregular_box& _That) noexcept(is_nothrow_copy_constructible_v<_Ty>) { - if (_STD addressof(_That) != this) { - if (_Engaged) { - _Val.~_Ty(); - _Engaged = false; - } + _CONSTEXPR20_DYNALLOC _Copyable_box& operator=(const _Copyable_box& _That) noexcept( + is_nothrow_copy_constructible_v<_Ty>) { + if (_STD addressof(_That) == this) { + return *this; + } - if (_That._Engaged) { - _Construct_in_place(_Val, _That._Val); - _Engaged = true; - } + if (_Engaged) { + _Val.~_Ty(); + _Engaged = false; + } + + if (_That._Engaged) { + _Construct_in_place(_Val, _That._Val); + _Engaged = true; } return *this; } // clang-format off - _Semiregular_box& operator=(_Semiregular_box&&) noexcept + _Copyable_box& operator=(_Copyable_box&&) noexcept requires movable<_Ty> && is_trivially_move_assignable_v<_Ty> = default; // clang-format on - _Semiregular_box& operator=(_Semiregular_box&& _That) noexcept(is_nothrow_move_constructible_v<_Ty>&& + _CONSTEXPR20_DYNALLOC _Copyable_box& operator=(_Copyable_box&& _That) noexcept( + is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) /* strengthened */ requires movable<_Ty> { if (_Engaged) { if (_That._Engaged) { @@ -346,7 +349,12 @@ namespace ranges { return *this; } - _Semiregular_box& operator=(_Semiregular_box&& _That) noexcept(is_nothrow_move_constructible_v<_Ty>) { + _CONSTEXPR20_DYNALLOC _Copyable_box& operator=(_Copyable_box&& _That) noexcept( + is_nothrow_move_constructible_v<_Ty>) { + if (_STD addressof(_That) == this) { + return *this; + } + if (_Engaged) { _Val.~_Ty(); _Engaged = false; @@ -383,26 +391,25 @@ namespace ranges { // clang-format off template <_Copy_constructible_object _Ty> - requires default_initializable<_Ty> - && (copyable<_Ty> - || (is_nothrow_copy_constructible_v<_Ty> - && (movable<_Ty> || is_nothrow_move_constructible_v<_Ty>))) - class _Semiregular_box<_Ty> { + requires copyable<_Ty> + || (is_nothrow_copy_constructible_v<_Ty> + && (movable<_Ty> || is_nothrow_move_constructible_v<_Ty>)) + class _Copyable_box<_Ty> { // provide the same API more efficiently when we can avoid the disengaged state // clang-format on public: - _Semiregular_box() = default; + _Copyable_box() requires default_initializable<_Ty> = default; template - constexpr _Semiregular_box(in_place_t, _Types&&... _Args) noexcept( + constexpr _Copyable_box(in_place_t, _Types&&... _Args) noexcept( is_nothrow_constructible_v<_Ty, _Types...>) // strengthened : _Val(_STD forward<_Types>(_Args)...) {} - _Semiregular_box(const _Semiregular_box&) = default; - _Semiregular_box(_Semiregular_box&&) = default; - _Semiregular_box& operator=(const _Semiregular_box&) requires copyable<_Ty> = default; - _Semiregular_box& operator=(_Semiregular_box&&) requires movable<_Ty> = default; + _Copyable_box(const _Copyable_box&) = default; + _Copyable_box(_Copyable_box&&) = default; + _Copyable_box& operator=(const _Copyable_box&) requires copyable<_Ty> = default; + _Copyable_box& operator=(_Copyable_box&&) requires movable<_Ty> = default; - _Semiregular_box& operator=(const _Semiregular_box& _That) noexcept { + _CONSTEXPR20_DYNALLOC _Copyable_box& operator=(const _Copyable_box& _That) noexcept { if (_STD addressof(_That) != this) { _Val.~_Ty(); _Construct_in_place(_Val, _That._Val); @@ -411,7 +418,7 @@ namespace ranges { return *this; } - _Semiregular_box& operator=(_Semiregular_box&& _That) noexcept { + _CONSTEXPR20_DYNALLOC _Copyable_box& operator=(_Copyable_box&& _That) noexcept { if (_STD addressof(_That) != this) { _Val.~_Ty(); _Construct_in_place(_Val, _STD move(_That._Val)); @@ -435,6 +442,184 @@ namespace ranges { /* [[no_unique_address]] */ _Ty _Val = _Ty(); }; + // CLASS TEMPLATE ranges::_Defaultabox + template + class _Defaultabox { // a simplified optional that augments movable types with default-constructibility + public: + constexpr _Defaultabox() noexcept : _Dummy{} {} + + ~_Defaultabox() requires is_trivially_destructible_v<_Ty> = default; + + _CONSTEXPR20_DYNALLOC ~_Defaultabox() { + if (_Engaged) { + _Val.~_Ty(); + } + } + + // clang-format off + _Defaultabox(const _Defaultabox&) + requires copy_constructible<_Ty> && is_trivially_copy_constructible_v<_Ty> = default; + // clang-format on + + _CONSTEXPR20_DYNALLOC _Defaultabox(const _Defaultabox& _That) requires copy_constructible<_Ty> + : _Engaged{_That._Engaged} { + if (_That._Engaged) { + _Construct_in_place(_Val, _That._Val); + } + } + + _Defaultabox(_Defaultabox&&) requires is_trivially_move_constructible_v<_Ty> = default; + + _CONSTEXPR20_DYNALLOC _Defaultabox(_Defaultabox&& _That) : _Engaged{_That._Engaged} { + if (_That._Engaged) { + _Construct_in_place(_Val, _STD move(_That._Val)); + } + } + + // clang-format off + _Defaultabox& operator=(const _Defaultabox&) noexcept + requires copyable<_Ty> && is_trivially_copy_assignable_v<_Ty> = default; + // clang-format on + + _CONSTEXPR20_DYNALLOC _Defaultabox& operator=(const _Defaultabox& _That) noexcept( + is_nothrow_copy_constructible_v<_Ty>&& + is_nothrow_copy_assignable_v<_Ty>) /* strengthened */ requires copyable<_Ty> { + if (_Engaged) { + if (_That._Engaged) { + _Val = _That._Val; + } else { + _Val.~_Ty(); + _Engaged = false; + } + } else { + if (_That._Engaged) { + _Construct_in_place(_Val, _That._Val); + _Engaged = true; + } else { + // nothing to do + } + } + + return *this; + } + + _Defaultabox& operator=(_Defaultabox&&) noexcept requires is_trivially_move_assignable_v<_Ty> = default; + + _CONSTEXPR20_DYNALLOC _Defaultabox& operator=(_Defaultabox&& _That) noexcept( + is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) /* strengthened */ { + if (_Engaged) { + if (_That._Engaged) { + _Val = _STD move(_That._Val); + } else { + _Val.~_Ty(); + _Engaged = false; + } + } else { + if (_That._Engaged) { + _Construct_in_place(_Val, _STD move(_That._Val)); + _Engaged = true; + } else { + // nothing to do + } + } + + return *this; + } + + _CONSTEXPR20_DYNALLOC _Defaultabox& operator=(_Ty&& _That) noexcept( + is_nothrow_move_constructible_v<_Ty>&& is_nothrow_move_assignable_v<_Ty>) { + if (_Engaged) { + _Val = _STD move(_That); + } else { + _Construct_in_place(_Val, _STD move(_That)); + _Engaged = true; + } + + return *this; + } + + _CONSTEXPR20_DYNALLOC _Defaultabox& operator=(const _Ty& _That) noexcept( + is_nothrow_copy_constructible_v<_Ty>&& is_nothrow_copy_assignable_v<_Ty>) requires copyable<_Ty> { + if (_Engaged) { + _Val = _That; + } else { + _Construct_in_place(_Val, _That); + _Engaged = true; + } + + return *this; + } + + constexpr explicit operator bool() const noexcept { + return _Engaged; + } + + _NODISCARD constexpr _Ty& operator*() noexcept { + _STL_INTERNAL_CHECK(_Engaged); + return _Val; + } + _NODISCARD constexpr const _Ty& operator*() const noexcept { + _STL_INTERNAL_CHECK(_Engaged); + return _Val; + } + + constexpr void _Reset() noexcept { + if (_Engaged) { + _Val.~_Ty(); + _Engaged = false; + } + } + + _NODISCARD constexpr bool operator==(const _Defaultabox& _That) const noexcept(noexcept(_Val == _That._Val)) { + _STL_INTERNAL_STATIC_ASSERT(equality_comparable<_Ty>); + return _Engaged == _That._Engaged && (!_Engaged || _Val == _That._Val); + } + + private: + union { + _Nontrivial_dummy_type _Dummy; + _Ty _Val; + }; + bool _Engaged = false; + }; + + // clang-format off + template + requires default_initializable<_Ty> + class _Defaultabox<_Ty> { // provide the same API more efficiently for default-constructible types + // clang-format on + public: + constexpr _Defaultabox& operator=(const _Ty& _Right) noexcept( + is_nothrow_copy_assignable_v<_Ty>) requires copyable<_Ty> { + _Value = _Right; + return *this; + } + constexpr _Defaultabox& operator=(_Ty&& _Right) noexcept(is_nothrow_move_assignable_v<_Ty>) { + _Value = _STD move(_Right); + return *this; + } + + constexpr explicit operator bool() const noexcept { + return true; + } + + _NODISCARD constexpr _Ty& operator*() noexcept { + return _Value; + } + _NODISCARD constexpr const _Ty& operator*() const noexcept { + return _Value; + } + + constexpr void _Reset() noexcept(noexcept(_Value = _Ty{})) { + _Value = _Ty{}; + } + + _NODISCARD bool operator==(const _Defaultabox&) const = default; + + private: + /* [[no_unique_address]] */ _Ty _Value{}; + }; + // CLASS TEMPLATE ranges::empty_view // clang-format off template @@ -476,7 +661,7 @@ namespace ranges { class single_view : public view_interface> { // clang-format on public: - single_view() = default; + single_view() requires default_initializable<_Ty> = default; constexpr explicit single_view(const _Ty& _Val_) noexcept(is_nothrow_copy_constructible_v<_Ty>) // strengthened : _Val{in_place, _Val_} {} constexpr explicit single_view(_Ty&& _Val_) noexcept(is_nothrow_move_constructible_v<_Ty>) // strengthened @@ -516,7 +701,7 @@ namespace ranges { } private: - /* [[no_unique_address]] */ _Semiregular_box<_Ty> _Val{}; + /* [[no_unique_address]] */ _Copyable_box<_Ty> _Val{}; }; namespace views { @@ -560,10 +745,10 @@ namespace ranges { }; template - requires semiregular<_Wi> + requires copyable<_Wi> struct _Ioterator { // clang-format on - /* [[no_unique_address]] */ _Wi _Current{}; + /* [[no_unique_address]] */ _Wi _Current; using iterator_concept = conditional_t<_Advanceable<_Wi>, random_access_iterator_tag, conditional_t<_Decrementable<_Wi>, bidirectional_iterator_tag, @@ -722,7 +907,7 @@ namespace ranges { // clang-format off template - requires _Weakly_equality_comparable_with<_Wi, _Bo> && semiregular<_Wi> + requires _Weakly_equality_comparable_with<_Wi, _Bo> && copyable<_Wi> struct _Iotinel { // clang-format on private: @@ -759,7 +944,7 @@ namespace ranges { // clang-format off template - requires _Weakly_equality_comparable_with<_Wi, _Bo> && semiregular<_Wi> + requires _Weakly_equality_comparable_with<_Wi, _Bo> && copyable<_Wi> class iota_view : public view_interface> { // clang-format on private: @@ -781,7 +966,7 @@ namespace ranges { } public: - iota_view() = default; + iota_view() requires default_initializable<_Wi> = default; constexpr explicit iota_view(_Wi _Value_) noexcept( is_nothrow_move_constructible_v<_Wi>&& is_nothrow_default_constructible_v<_Bo>) // strengthened @@ -875,14 +1060,13 @@ namespace ranges { private: class _Iterator { private: - basic_istream_view* _Parent = nullptr; + basic_istream_view* _Parent; public: using iterator_concept = input_iterator_tag; using difference_type = ptrdiff_t; using value_type = _Ty; - _Iterator() = default; constexpr explicit _Iterator(basic_istream_view& _Parent_) noexcept : _Parent{_STD addressof(_Parent_)} {} _Iterator(const _Iterator&) = delete; @@ -894,9 +1078,6 @@ namespace ranges { _Iterator& operator++() { #if _ITERATOR_DEBUG_LEVEL != 0 // Per LWG-3489 - _STL_VERIFY(_Parent != nullptr, "cannot increment default-initialized istream_view iterator"); - _STL_VERIFY( - _Parent->_Stream != nullptr, "cannot increment istream_view iterator with uninitialized stream"); _STL_VERIFY(!_Parent->_Stream_at_end(), "cannot increment istream_view iterator at end of stream"); #endif // _ITERATOR_DEBUG_LEVEL != 0 *_Parent->_Stream >> _Parent->_Val; @@ -910,32 +1091,26 @@ namespace ranges { _NODISCARD _Ty& operator*() const noexcept /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 // Per LWG-3489 - _STL_VERIFY(_Parent != nullptr, "cannot dereference default-initialized istream_view iterator"); - _STL_VERIFY( - _Parent->_Stream != nullptr, "cannot dereference istream_view iterator with uninitialized stream"); _STL_VERIFY(!_Parent->_Stream_at_end(), "cannot dereference istream_view iterator at end of stream"); #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Parent->_Val; } _NODISCARD friend bool operator==(const _Iterator& _Left, default_sentinel_t) noexcept /* strengthened */ { - return _Left._Parent == nullptr || _Left._Parent->_Stream_at_end(); + return _Left._Parent->_Stream_at_end(); } }; - basic_istream<_Elem, _Traits>* _Stream = nullptr; - _Ty _Val = _Ty{}; + basic_istream<_Elem, _Traits>* _Stream; + _Ty _Val = _Ty{}; // Per LWG issue submitted but unnumbered as of 2021-06-15 public: - basic_istream_view() = default; constexpr explicit basic_istream_view(basic_istream<_Elem, _Traits>& _Stream_) noexcept( is_nothrow_default_constructible_v<_Ty>) // strengthened : _Stream{_STD addressof(_Stream_)} {} _NODISCARD constexpr auto begin() { - if (_Stream) { - *_Stream >> _Val; - } + *_Stream >> _Val; return _Iterator{*this}; } @@ -961,14 +1136,12 @@ namespace ranges { class ref_view : public view_interface> { // clang-format on private: - _Rng* _Range = nullptr; + _Rng* _Range; static void _Rvalue_poison(_Rng&); static void _Rvalue_poison(_Rng&&) = delete; public: - constexpr ref_view() noexcept = default; - // clang-format off template <_Not_same_as _OtherRng> constexpr ref_view(_OtherRng&& _Other) noexcept( @@ -1082,7 +1255,7 @@ namespace ranges { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; - /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{}; + /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{}; template // TRANSITION, LWG-3289 struct _Category_base {}; @@ -1115,7 +1288,8 @@ namespace ranges { using value_type = range_value_t<_Vw>; using difference_type = range_difference_t<_Vw>; - _Iterator() = default; + _Iterator() requires default_initializable> = default; + constexpr _Iterator(filter_view& _Parent_, iterator_t<_Vw> _Current_) noexcept( is_nothrow_move_constructible_v>) // strengthened : _Current(_STD move(_Current_)), _Parent{_STD addressof(_Parent_)} { @@ -1248,7 +1422,10 @@ namespace ranges { }; public: - filter_view() = default; + // clang-format off + filter_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default; + // clang-format on + constexpr filter_view(_Vw _Range_, _Pr _Pred_) noexcept( is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened : _Range(_STD move(_Range_)), _Pred{in_place, _STD move(_Pred_)} {} @@ -1263,7 +1440,7 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pred, "value-initialized filter_view has no predicate"); + _STL_VERIFY(_Pred, "filter_view has no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_Pred; } @@ -1305,7 +1482,7 @@ namespace ranges { private: template struct _Partial : _Pipe::_Base<_Partial<_Pr>> { - /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; + /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred; template _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( @@ -1361,7 +1538,7 @@ namespace ranges { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; - /* [[no_unique_address]] */ _Semiregular_box<_Fn> _Fun{}; + /* [[no_unique_address]] */ _Copyable_box<_Fn> _Fun{}; template class _Sentinel; @@ -1413,7 +1590,7 @@ namespace ranges { using value_type = remove_cvref_t>>; using difference_type = range_difference_t<_Base>; - _Iterator() = default; + _Iterator() requires default_initializable> = default; constexpr _Iterator(_Parent_t& _Parent_, iterator_t<_Base> _Current_) noexcept( is_nothrow_move_constructible_v>) // strengthened @@ -1707,11 +1884,12 @@ namespace ranges { noexcept(_Left._Last - _Get_current(_Right))) /* strengthened */ { return _Left._Last - _Get_current(_Right); } - // clang-format on }; public: - transform_view() = default; + transform_view() requires default_initializable<_Vw> && default_initializable<_Fn> = default; + // clang-format on + constexpr transform_view(_Vw _Range_, _Fn _Fun_) noexcept( is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Fn>) // strengthened : _Range(_STD move(_Range_)), _Fun{in_place, _STD move(_Fun_)} {} @@ -1791,7 +1969,7 @@ namespace ranges { private: template struct _Partial : _Pipe::_Base<_Partial<_Fn>> { - /* [[no_unique_address]] */ _Semiregular_box<_Fn> _Fun; + /* [[no_unique_address]] */ _Copyable_box<_Fn> _Fun; template _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( @@ -1907,7 +2085,7 @@ namespace ranges { }; public: - take_view() = default; + take_view() requires default_initializable<_Vw> = default; constexpr take_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept( is_nothrow_move_constructible_v<_Vw>) // strengthened @@ -2136,7 +2314,7 @@ namespace ranges { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; - /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{}; + /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{}; template class _Sentinel { @@ -2211,7 +2389,9 @@ namespace ranges { }; public: - take_while_view() = default; + // clang-format off + take_while_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default; + // clang-format on constexpr take_while_view(_Vw _Range_, _Pr _Pred_) noexcept( is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened @@ -2227,7 +2407,7 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pred, "value-initialized take_while_view has no predicate"); + _STL_VERIFY(_Pred, "take_while_view has no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_Pred; } @@ -2253,7 +2433,7 @@ namespace ranges { requires (!_Simple_view<_Vw>) { // clang-format on #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pred, "value-initialized take_while_view cannot call end"); + _STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; } @@ -2264,7 +2444,7 @@ namespace ranges { requires range && indirect_unary_predicate> { // clang-format on #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pred, "value-initialized take_while_view cannot call end"); + _STL_VERIFY(_Pred, "cannot call end on a take_while_view with no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return _Sentinel{_RANGES end(_Range), _STD addressof(*_Pred)}; } @@ -2279,7 +2459,7 @@ namespace ranges { private: template struct _Partial : _Pipe::_Base<_Partial<_Pr>> { - /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; + /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred; template _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( @@ -2321,8 +2501,34 @@ namespace ranges { /* [[no_unique_address]] */ _Vw _Range{}; range_difference_t<_Vw> _Count = 0; + _NODISCARD constexpr auto _Find_first() { + if constexpr (sized_range<_Vw>) { + _STL_INTERNAL_STATIC_ASSERT(!random_access_range<_Vw>); + auto _Offset = _RANGES distance(_Range); + if constexpr (bidirectional_range<_Vw> && common_range<_Vw>) { + if (_Count >= _Offset / 2) { + auto _Result = _RANGES end(_Range); + while (_Offset > _Count) { + --_Offset; + --_Result; + } + + return _Result; + } + } + + if (_Offset > _Count) { + _Offset = _Count; + } + + return _RANGES next(_RANGES begin(_Range), _Offset); + } else { + return _RANGES next(_RANGES begin(_Range), _Count, _RANGES end(_Range)); + } + } + public: - drop_view() = default; + drop_view() requires default_initializable<_Vw> = default; constexpr drop_view(_Vw _Range_, const range_difference_t<_Vw> _Count_) noexcept( is_nothrow_move_constructible_v<_Vw>) // strengthened @@ -2354,31 +2560,7 @@ namespace ranges { } } - iterator_t<_Vw> _Result; - if constexpr (sized_range<_Vw>) { - auto _Offset = _RANGES distance(_Range); - if constexpr (bidirectional_range<_Vw> && common_range<_Vw>) { - if (_Count >= _Offset / 2) { - _Result = _RANGES end(_Range); - while (_Offset > _Count) { - --_Offset; - --_Result; - } - - this->_Set_cache(_Range, _Result); - return _Result; - } - } - - if (_Offset > _Count) { - _Offset = _Count; - } - - _Result = _RANGES next(_RANGES begin(_Range), _Offset); - } else { - _Result = _RANGES next(_RANGES begin(_Range), _Count, _RANGES end(_Range)); - } - + same_as> auto _Result = _Find_first(); if constexpr (forward_range<_Vw>) { this->_Set_cache(_Range, _Result); } @@ -2566,10 +2748,12 @@ namespace ranges { // clang-format on private: /* [[no_unique_address]] */ _Vw _Range{}; - /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred{}; + /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred{}; public: - drop_while_view() = default; + // clang-format off + drop_while_view() requires default_initializable<_Vw> && default_initializable<_Pr> = default; + // clang-format on constexpr drop_while_view(_Vw _Range_, _Pr _Pred_) noexcept( is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pr>) // strengthened @@ -2585,7 +2769,7 @@ namespace ranges { _NODISCARD constexpr const _Pr& pred() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 - _STL_VERIFY(_Pred, "value-initialized drop_while_view has no predicate"); + _STL_VERIFY(_Pred, "drop_while_view has no predicate"); #endif // _CONTAINER_DEBUG_LEVEL > 0 return *_Pred; } @@ -2626,7 +2810,7 @@ namespace ranges { private: template struct _Partial : _Pipe::_Base<_Partial<_Pr>> { - /* [[no_unique_address]] */ _Semiregular_box<_Pr> _Pred; + /* [[no_unique_address]] */ _Copyable_box<_Pr> _Pred; template _NODISCARD constexpr auto operator()(_Rng&& _Range) const& noexcept( @@ -2671,7 +2855,7 @@ namespace ranges { template class _Join_view_base : public view_interface> { protected: - /* [[no_unique_address]] */ views::all_t> _Inner{}; + /* [[no_unique_address]] */ _Defaultabox>> _Inner{}; }; // clang-format off @@ -2735,7 +2919,7 @@ namespace ranges { static constexpr bool _Deref_is_glvalue = is_reference_v<_InnerRng<_Const>>; /* [[no_unique_address]] */ _OuterIter _Outer{}; - /* [[no_unique_address]] */ _InnerIter _Inner{}; + /* [[no_unique_address]] */ _Defaultabox<_InnerIter> _Inner{}; // per LWG issue unfiled as of 2021-06-14 _Parent_t* _Parent{}; constexpr auto& _Update_inner(_InnerRng<_Const> _Range) { @@ -2743,7 +2927,7 @@ namespace ranges { return _Range; } else { _Parent->_Inner = views::all(_STD move(_Range)); - return _Parent->_Inner; + return *_Parent->_Inner; } } @@ -2752,12 +2936,12 @@ namespace ranges { for (; _Outer != _Last; ++_Outer) { auto& _Tmp = _Update_inner(*_Outer); _Inner = _RANGES begin(_Tmp); - if (_Inner != _RANGES end(_Tmp)) { + if (*_Inner != _RANGES end(_Tmp)) { return; } } if constexpr (_Deref_is_glvalue) { - _Inner = _InnerIter{}; + _Inner._Reset(); } } @@ -2769,9 +2953,9 @@ namespace ranges { if constexpr (_Deref_is_glvalue) { _Last = _RANGES end(*_Outer); } else { - _Last = _RANGES end(_Parent->_Inner); + _Last = _RANGES end(*_Parent->_Inner); } - _STL_VERIFY(_Inner != _Last, "cannot dereference join_view end iterator"); + _STL_VERIFY(_Inner && *_Inner != _Last, "cannot dereference join_view end iterator"); } constexpr void _Same_range(const _Iterator& _Right) const noexcept { @@ -2791,7 +2975,9 @@ namespace ranges { using value_type = range_value_t<_InnerRng<_Const>>; using difference_type = common_type_t, range_difference_t<_InnerRng<_Const>>>; - _Iterator() = default; + // clang-format off + _Iterator() requires default_initializable<_OuterIter> && default_initializable<_InnerIter> = default; + // clang-format on constexpr _Iterator(_Parent_t& _Parent_, _OuterIter _Outer_) : _Outer{_STD move(_Outer_)}, _Parent{_STD addressof(_Parent_)} { @@ -2811,11 +2997,11 @@ namespace ranges { : _Outer{_STD move(_It._Outer)}, _Inner{_STD move(_It._Inner)}, _Parent{_It._Parent} {} // clang-format on - _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(*_Inner)) /* strengthened */ { + _NODISCARD constexpr decltype(auto) operator*() const noexcept(noexcept(**_Inner)) /* strengthened */ { #if _ITERATOR_DEBUG_LEVEL != 0 _Check_dereference(); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return *_Inner; + return **_Inner; } // clang-format off @@ -2825,17 +3011,17 @@ namespace ranges { #if _ITERATOR_DEBUG_LEVEL != 0 _Check_dereference(); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return _Inner; + return *_Inner; } constexpr _Iterator& operator++() { if constexpr (_Deref_is_glvalue) { - if (++_Inner == _RANGES end(*_Outer)) { + if (++*_Inner == _RANGES end(*_Outer)) { ++_Outer; _Satisfy(); } } else { - if (++_Inner == _RANGES end(_Parent->_Inner)) { + if (++*_Inner == _RANGES end(*_Parent->_Inner)) { ++_Outer; _Satisfy(); } @@ -2862,11 +3048,11 @@ namespace ranges { --_Outer; _Inner = _RANGES end(*_Outer); } - while (_Inner == _RANGES begin(*_Outer)) { + while (*_Inner == _RANGES begin(*_Outer)) { --_Outer; - _Inner = _RANGES end(*_Outer); + *_Inner = _RANGES end(*_Outer); } - --_Inner; + --*_Inner; return *this; } @@ -2893,23 +3079,23 @@ namespace ranges { } _NODISCARD friend constexpr decltype(auto) iter_move(const _Iterator& _It) noexcept( - noexcept(_RANGES iter_move(_It._Inner))) { + noexcept(_RANGES iter_move(*_It._Inner))) { #if _ITERATOR_DEBUG_LEVEL != 0 _It._Check_dereference(); #endif // _ITERATOR_DEBUG_LEVEL != 0 - return _RANGES iter_move(_It._Inner); + return _RANGES iter_move(*_It._Inner); } // clang-format off friend constexpr void iter_swap(const _Iterator& _Left, const _Iterator& _Right) noexcept( - noexcept(_RANGES iter_swap(_Left._Inner, _Right._Inner))) + noexcept(_RANGES iter_swap(*_Left._Inner, *_Right._Inner))) requires indirectly_swappable<_InnerIter> { // clang-format on #if _ITERATOR_DEBUG_LEVEL != 0 _Left._Check_dereference(); _Right._Check_dereference(); #endif // _ITERATOR_DEBUG_LEVEL != 0 - _RANGES iter_swap(_Left._Inner, _Right._Inner); + _RANGES iter_swap(*_Left._Inner, *_Right._Inner); } }; @@ -2961,7 +3147,8 @@ namespace ranges { }; public: - join_view() = default; + join_view() requires default_initializable<_Vw> = default; + constexpr explicit join_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)) {} @@ -3048,7 +3235,7 @@ namespace ranges { template class _Split_view_base : public view_interface> { protected: - /* [[no_unique_address]] */ iterator_t<_Vw> _Current{}; + /* [[no_unique_address]] */ _Defaultabox> _Current{}; }; template @@ -3103,7 +3290,7 @@ namespace ranges { if constexpr (forward_range<_BaseTy>) { return this->_Current; } else { - return _Parent->_Current; + return *_Parent->_Current; } } @@ -3111,7 +3298,7 @@ namespace ranges { if constexpr (forward_range<_BaseTy>) { return this->_Current; } else { - return _Parent->_Current; + return *_Parent->_Current; } } @@ -3351,7 +3538,10 @@ namespace ranges { }; public: - split_view() = default; + // clang-format off + split_view() requires default_initializable<_Vw> && default_initializable<_Pat> = default; + // clang-format on + constexpr split_view(_Vw _Range_, _Pat _Pattern_) noexcept( is_nothrow_move_constructible_v<_Vw>&& is_nothrow_move_constructible_v<_Pat>) // strengthened : _Range(_STD move(_Range_)), _Pattern(_STD move(_Pattern_)) {} @@ -3512,7 +3702,8 @@ namespace ranges { /* [[no_unique_address]] */ _Vw _Base{}; public: - common_view() = default; + common_view() requires default_initializable<_Vw> = default; + constexpr explicit common_view(_Vw _Base_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Base(_STD move(_Base_)) {} @@ -3629,7 +3820,8 @@ namespace ranges { using _Rev_iter = reverse_iterator>; public: - reverse_view() = default; + reverse_view() requires default_initializable<_Vw> = default; + constexpr explicit reverse_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)) {} @@ -3822,7 +4014,7 @@ namespace ranges { using value_type = remove_cvref_t>>; using difference_type = range_difference_t<_Base>; - _Iterator() = default; + _Iterator() requires default_initializable> = default; constexpr explicit _Iterator(iterator_t<_Base> _Current_) noexcept( is_nothrow_move_constructible_v>) // strengthened @@ -4078,7 +4270,7 @@ namespace ranges { }; public: - elements_view() = default; + elements_view() requires default_initializable<_Vw> = default; constexpr explicit elements_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened : _Range(_STD move(_Range_)) {} diff --git a/stl/inc/span b/stl/inc/span index 45c51c806ae..e4fb8604ccb 100644 --- a/stl/inc/span +++ b/stl/inc/span @@ -232,7 +232,7 @@ class span; #ifdef __cpp_lib_concepts namespace ranges { template - inline constexpr bool enable_view> = _Extent == 0 || _Extent == dynamic_extent; + inline constexpr bool enable_view> = true; template inline constexpr bool enable_borrowed_range> = true; } // namespace ranges diff --git a/stl/inc/xutility b/stl/inc/xutility index d58d4fa96aa..f3adc622ee5 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -810,7 +810,7 @@ _NODISCARD constexpr auto _To_signed_like(const _Ty _Value) noexcept { // CONCEPT weakly_incrementable // clang-format off template -concept weakly_incrementable = default_initializable<_Ty> && movable<_Ty> && requires(_Ty __i) { +concept weakly_incrementable = movable<_Ty> && requires(_Ty __i) { typename iter_difference_t<_Ty>; requires _Signed_integer_like>; { ++__i } -> same_as<_Ty&>; @@ -2860,7 +2860,7 @@ namespace ranges { // clang-format off // CONCEPT ranges::view template - concept view = range<_Ty> && movable<_Ty> && default_initializable<_Ty> && enable_view<_Ty>; + concept view = range<_Ty> && movable<_Ty> && enable_view<_Ty>; #endif // TRANSITION, GH-1814 // CONCEPT ranges::output_range @@ -3507,7 +3507,7 @@ namespace ranges { } public: - subrange() = default; + subrange() requires default_initializable<_It> = default; template <_Convertible_to_non_slicing<_It> _It2> constexpr subrange(_It2 _First_, _Se _Last_) requires (!_Store_size) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 66a66b4464a..99254ec741b 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -245,6 +245,7 @@ // P2102R0 Making "Implicit Expression Variations" More Explicit // P2106R0 Range Algorithm Result Types // P2116R0 Removing tuple-Like Protocol Support From Fixed-Extent span +// P2325R3 Views Should Not Be Required To Be Default Constructible // P????R? directory_entry::clear_cache() // _HAS_CXX20 indirectly controls: @@ -1279,7 +1280,7 @@ #define __cpp_lib_polymorphic_allocator 201902L #if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395 and GH-1814 -#define __cpp_lib_ranges 201911L +#define __cpp_lib_ranges 202106L #endif // _HAS_CXX23 && defined(__cpp_lib_concepts) #define __cpp_lib_remove_cvref 201711L diff --git a/tests/std/include/range_algorithm_support.hpp b/tests/std/include/range_algorithm_support.hpp index a5680543ad4..e00e9c1abd2 100644 --- a/tests/std/include/range_algorithm_support.hpp +++ b/tests/std/include/range_algorithm_support.hpp @@ -370,7 +370,7 @@ namespace test { using Consterator = iterator; // output iterator operations - iterator() = default; + iterator() requires at_least || (Eq == CanCompare::yes) = default; constexpr explicit iterator(Element* ptr) noexcept : ptr_{ptr} {} @@ -624,7 +624,7 @@ namespace test { public: static_assert(Copy == Copyability::immobile); - range_base() = default; + range_base() = delete; constexpr explicit range_base(span elements) noexcept : elements_{elements} {} range_base(const range_base&) = delete; @@ -640,7 +640,7 @@ namespace test { template class range_base { public: - range_base() = default; + range_base() = delete; constexpr explicit range_base(span elements) noexcept : elements_{elements} {} constexpr range_base(range_base&& that) noexcept diff --git a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp index dac065087d3..988d907579f 100644 --- a/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp +++ b/tests/std/tests/P0784R7_library_support_for_more_constexpr_containers/test.cpp @@ -412,11 +412,11 @@ struct Alloc { allocator{}.deallocate(ptr, n); } - constexpr void construct(value_type* ptr, value_type n) requires(Construct) { + constexpr void construct(value_type* ptr, value_type n) requires Construct { construct_at(ptr, n); } - constexpr void destroy(value_type* ptr) requires(Destroy) { + constexpr void destroy(value_type* ptr) requires Destroy { destroy_at(ptr); } diff --git a/tests/std/tests/P0896R4_counted_iterator/test.cpp b/tests/std/tests/P0896R4_counted_iterator/test.cpp index 0cec96ad8db..e35b4fcacf0 100644 --- a/tests/std/tests/P0896R4_counted_iterator/test.cpp +++ b/tests/std/tests/P0896R4_counted_iterator/test.cpp @@ -53,7 +53,10 @@ struct instantiator { int input[5] = {1, 2, 3, 4, 5}; // [counted.iter.const] { - [[maybe_unused]] counted_iterator defaultConstructed{}; + STATIC_ASSERT(default_initializable> == default_initializable); + if constexpr (default_initializable) { + [[maybe_unused]] counted_iterator defaultConstructed{}; + } counted_iterator constructed(Iter{input}, iter_difference_t{2}); counted_iterator constructedEmpty{Iter{input}, iter_difference_t{0}}; @@ -198,7 +201,7 @@ struct instantiator { const same_as> auto diff2 = iter2 - iter1; assert(diff2 == -1); } - { // difference value-initialized + if constexpr (default_initializable) { // difference value-initialized const same_as> auto diff1 = counted_iterator{} - counted_iterator{}; assert(diff1 == 0); } @@ -269,7 +272,7 @@ struct instantiator { assert(iter1 <=> iter1 == strong_ordering::equal); assert(iter1 <=> iter1 == strong_ordering::equivalent); } - { // spaceship value-initialized + if constexpr (default_initializable) { // spaceship value-initialized assert(counted_iterator{} <=> counted_iterator{} == strong_ordering::equal); assert(counted_iterator{} <=> counted_iterator{} == strong_ordering::equivalent); } diff --git a/tests/std/tests/P0896R4_istream_view/test.cpp b/tests/std/tests/P0896R4_istream_view/test.cpp index 346c66d3cdc..df83592d867 100644 --- a/tests/std/tests/P0896R4_istream_view/test.cpp +++ b/tests/std/tests/P0896R4_istream_view/test.cpp @@ -46,30 +46,20 @@ void test_one_type() { // validate constructors istringstream nonempty_stream{"0"}; istringstream empty_intstream{}; - R default_constructed{}; R empty_constructed{empty_intstream}; R non_empty_constructed{nonempty_stream}; - static_assert(is_nothrow_constructible_v == is_nothrow_default_constructible_v); static_assert(is_nothrow_constructible_v == is_nothrow_default_constructible_v); // validate member begin // NOTE: begin() consumes the first token - (void) default_constructed.begin(); // default-constructed basic_istream_view doesn't model range. assert(empty_constructed.begin() == default_sentinel); assert(non_empty_constructed.begin() != default_sentinel); - // validate default constructed istream::iterator - { - const ranges::iterator_t default_constructed_it; - assert(default_constructed_it == default_sentinel); - static_assert(noexcept(default_constructed_it == default_sentinel)); - } - // validate member end - static_assert(same_as); - static_assert(noexcept(default_constructed.end())); - static_assert(noexcept(ranges::end(default_constructed))); + static_assert(same_as); + static_assert(noexcept(empty_constructed.end())); + static_assert(noexcept(ranges::end(empty_constructed))); // Nonexistent member functions static_assert(!CanMemberSize); @@ -97,15 +87,11 @@ void test_one_type() { istringstream some_stream{"42"}; constexpr bool test_constexpr() { - // Default constructor is constexpr - ranges::basic_istream_view empty{}; - - // begin is constexpr??!? - (void) empty.begin(); - // stream constructor is constexpr ranges::basic_istream_view meow{some_stream}; + // begin is constexpr, but realistically unusable in a constant expression + // end is constexpr (void) meow.end(); diff --git a/tests/std/tests/P0896R4_istream_view_death/test.cpp b/tests/std/tests/P0896R4_istream_view_death/test.cpp index 22f76db2769..fbad6ceae6b 100644 --- a/tests/std/tests/P0896R4_istream_view_death/test.cpp +++ b/tests/std/tests/P0896R4_istream_view_death/test.cpp @@ -13,46 +13,6 @@ using namespace std; using iview = ranges::basic_istream_view; -void test_preincrement_default_initialized() { - ranges::iterator_t it; - (void) ++it; -} - -void test_postincrement_default_initialized() { - ranges::iterator_t it; - (void) it++; -} - -void test_dereference_default_initialized() { - ranges::iterator_t it; - (void) *it; -} - -void test_preincrement_no_stream() { - iview v; - auto it = v.begin(); - (void) ++it; -} - -void test_postincrement_no_stream() { - iview v; - auto it = v.begin(); - (void) it++; -} - -void test_dereference_no_stream() { - iview v; - auto it = v.begin(); - (void) *it; -} - -void test_compare_no_stream() { - iview v; - auto it = v.begin(); - auto se = v.end(); - (void) (it == se); -} - void test_preincrement_end_of_stream() { istringstream stream; iview view{stream}; @@ -79,13 +39,6 @@ int main(int argc, char* argv[]) { #if _ITERATOR_DEBUG_LEVEL != 0 exec.add_death_tests({ - test_preincrement_default_initialized, - test_postincrement_default_initialized, - test_dereference_default_initialized, - test_preincrement_no_stream, - test_postincrement_no_stream, - test_dereference_no_stream, - test_compare_no_stream, test_preincrement_end_of_stream, test_postincrement_end_of_stream, test_dereference_end_of_stream, diff --git a/tests/std/tests/P0896R4_ranges_alg_adjacent_find/test.cpp b/tests/std/tests/P0896R4_ranges_alg_adjacent_find/test.cpp index 3c784d5bb1d..f9df7429977 100644 --- a/tests/std/tests/P0896R4_ranges_alg_adjacent_find/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_adjacent_find/test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -53,8 +54,10 @@ int main() { } struct instantiator { + static constexpr int some_ints[] = {1, 2, 3}; template - static void call(Fwd&& fwd = {}) { + static void call() { + Fwd fwd{std::span{some_ints}}; using ranges::adjacent_find, ranges::iterator_t; (void) adjacent_find(fwd); diff --git a/tests/std/tests/P0896R4_ranges_alg_binary_search/test.cpp b/tests/std/tests/P0896R4_ranges_alg_binary_search/test.cpp index 345f9cf7eb5..e89752adc74 100644 --- a/tests/std/tests/P0896R4_ranges_alg_binary_search/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_binary_search/test.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -30,7 +31,7 @@ struct empty_ranges { template static constexpr void call() { // Validate empty ranges - const Fwd range{}; + const Fwd range{span{}}; ASSERT(ranges::lower_bound(range, 42, ranges::less{}, get_first) == ranges::end(range)); ASSERT(ranges::lower_bound(ranges::begin(range), ranges::end(range), 42, ranges::less{}, get_first) diff --git a/tests/std/tests/P0896R4_ranges_alg_equal/test.cpp b/tests/std/tests/P0896R4_ranges_alg_equal/test.cpp index 6d5d00c1cb7..7a85024c423 100644 --- a/tests/std/tests/P0896R4_ranges_alg_equal/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_equal/test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -87,9 +88,12 @@ int main() { struct instantiator { template - static void call(In1&& in1 = {}, In2&& in2 = {}) { + static void call() { using ranges::begin, ranges::end, ranges::equal, ranges::iterator_t; + In1 in1{std::span{}}; + In2 in2{std::span{}}; + if constexpr (!is_permissive) { (void) equal(in1, in2); (void) equal(begin(in1), end(in1), begin(in2), end(in2)); diff --git a/tests/std/tests/P0896R4_ranges_alg_find_end/test.cpp b/tests/std/tests/P0896R4_ranges_alg_find_end/test.cpp index 81880bacca8..feb9cd31793 100644 --- a/tests/std/tests/P0896R4_ranges_alg_find_end/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_find_end/test.cpp @@ -79,10 +79,13 @@ int main() { #ifndef _PREFAST_ // TRANSITION, GH-1030 struct instantiator { template - static void call(Fwd1&& fwd1 = {}, Fwd2&& fwd2 = {}) { + static void call() { if constexpr (!is_permissive) { // These fail to compile in C1XX's permissive mode due to VSO-566808 using ranges::iterator_t; + Fwd1 fwd1{std::span{}}; + Fwd2 fwd2{std::span{}}; + (void) ranges::find_end(fwd1, fwd2); (void) ranges::find_end(ranges::begin(fwd1), ranges::end(fwd1), ranges::begin(fwd2), ranges::end(fwd2)); diff --git a/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp b/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp index ac24c5645f2..f7203052ab5 100644 --- a/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_heap/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,7 @@ struct empty_ranges { template static constexpr void call() { // Validate empty ranges (only make_heap and sort_heap accept empty ranges) - const Range range{}; + const Range range{span{}}; ASSERT(ranges::make_heap(range, ranges::less{}, get_first) == ranges::end(range)); ASSERT(ranges::make_heap(ranges::begin(range), ranges::end(range), ranges::less{}, get_first) diff --git a/tests/std/tests/P0896R4_ranges_alg_includes/test.cpp b/tests/std/tests/P0896R4_ranges_alg_includes/test.cpp index 54929f26822..19a62c027ca 100644 --- a/tests/std/tests/P0896R4_ranges_alg_includes/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_includes/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -38,14 +39,14 @@ struct instantiator { } { // Validate range overload, empty haystack - Haystack haystack{}; + Haystack haystack{span{}}; Needle needle{needle_elements}; const same_as auto result = includes(haystack, needle, ranges::less{}, get_first, add_one); assert(!result); } { // Validate iterator overload, empty needle Haystack haystack{haystack_elements}; - Needle needle{}; + Needle needle{span{}}; const same_as auto result = includes( haystack.begin(), haystack.end(), needle.begin(), needle.end(), ranges::less{}, get_first, add_one); assert(result); diff --git a/tests/std/tests/P0896R4_ranges_alg_inplace_merge/test.cpp b/tests/std/tests/P0896R4_ranges_alg_inplace_merge/test.cpp index 9cf822b5dcb..f0b2f7729da 100644 --- a/tests/std/tests/P0896R4_ranges_alg_inplace_merge/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_inplace_merge/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -31,7 +32,7 @@ struct instantiator { assert(equal(input, expected)); // Validate empty range - const Range empty_range{}; + const Range empty_range{span{}}; const same_as> auto empty_result = inplace_merge(empty_range, empty_range.begin(), ranges::less{}, get_first); assert(empty_result == empty_range.begin()); @@ -47,7 +48,7 @@ struct instantiator { assert(equal(input, expected)); // Validate empty range - const Range empty_range{}; + const Range empty_range{span{}}; const same_as> auto empty_result = inplace_merge(empty_range.begin(), empty_range.begin(), empty_range.end(), ranges::less{}, get_first); assert(empty_result == empty_range.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_is_permutation/test.cpp b/tests/std/tests/P0896R4_ranges_alg_is_permutation/test.cpp index ecf2f498f1c..308e50f45e3 100644 --- a/tests/std/tests/P0896R4_ranges_alg_is_permutation/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_is_permutation/test.cpp @@ -49,7 +49,7 @@ struct instantiator { { // negative case [different lengths] - const Fwd2 suffix2{std::span{not_pairs}.subspan<2>()}; + const Fwd2 suffix2{span{not_pairs}.subspan<2>()}; assert(!ranges::is_permutation(range1, suffix2, ranges::equal_to{}, get_first, identity{})); assert(!ranges::is_permutation(suffix2, range1, ranges::equal_to{}, identity{}, get_first)); assert(!ranges::is_permutation(ranges::begin(range1), ranges::end(range1), ranges::begin(suffix2), @@ -74,16 +74,16 @@ struct instantiator { { // negative case [only final elements differ] - const Fwd1 r1{std::span{pairs}.subspan<0, 3>()}; - const Fwd2 r2{std::span{not_pairs}.subspan<0, 3>()}; + const Fwd1 r1{span{pairs}.subspan<0, 3>()}; + const Fwd2 r2{span{not_pairs}.subspan<0, 3>()}; assert(!ranges::is_permutation(r1, r2, ranges::equal_to{}, get_first, identity{})); assert(!ranges::is_permutation(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), ranges::equal_to{}, get_first, identity{})); } { // negative case [only initial elements differ] - const Fwd1 r1{std::span{pairs}.subspan<1, 3>()}; - const Fwd2 r2{std::span{not_pairs}.subspan<4, 3>()}; + const Fwd1 r1{span{pairs}.subspan<1, 3>()}; + const Fwd2 r2{span{not_pairs}.subspan<4, 3>()}; assert(!ranges::is_permutation(r1, r2, ranges::equal_to{}, get_first, identity{})); assert(!ranges::is_permutation(ranges::begin(r1), ranges::end(r1), ranges::begin(r2), ranges::end(r2), ranges::equal_to{}, get_first, identity{})); diff --git a/tests/std/tests/P0896R4_ranges_alg_lexicographical_compare/test.cpp b/tests/std/tests/P0896R4_ranges_alg_lexicographical_compare/test.cpp index d3fcc5dedc9..fa4ec994a72 100644 --- a/tests/std/tests/P0896R4_ranges_alg_lexicographical_compare/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_lexicographical_compare/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -87,20 +88,20 @@ struct instantiator { } { - In1 empty1{}; + In1 empty1{span{}}; In2 range2{right_equal}; const same_as auto result = lexicographical_compare(empty1, range2, less{}, get_first, get_second); assert(result); } { In1 range1{left}; - In2 empty2{}; + In2 empty2{span{}}; const same_as auto result = lexicographical_compare(range1, empty2, less{}, get_first, get_second); assert(!result); } { - In1 empty1{}; - In2 empty2{}; + In1 empty1{span{}}; + In2 empty2{span{}}; const same_as auto result = lexicographical_compare(empty1, empty2, less{}, get_first, get_second); assert(!result); } @@ -173,7 +174,7 @@ struct instantiator { } { - In1 empty1{}; + In1 empty1{span{}}; In2 range2{right_equal}; const same_as auto result = lexicographical_compare( empty1.begin(), empty1.end(), range2.begin(), range2.end(), less{}, get_first, get_second); @@ -181,14 +182,14 @@ struct instantiator { } { In1 range1{left}; - In2 empty2{}; + In2 empty2{span{}}; const same_as auto result = lexicographical_compare( range1.begin(), range1.end(), empty2.begin(), empty2.end(), less{}, get_first, get_second); assert(!result); } { - In1 empty1{}; - In2 empty2{}; + In1 empty1{span{}}; + In2 empty2{span{}}; const same_as auto result = lexicographical_compare( empty1.begin(), empty1.end(), empty2.begin(), empty2.end(), less{}, get_first, get_second); assert(!result); diff --git a/tests/std/tests/P0896R4_ranges_alg_merge/test.cpp b/tests/std/tests/P0896R4_ranges_alg_merge/test.cpp index d9475353bb2..f536f27be6c 100644 --- a/tests/std/tests/P0896R4_ranges_alg_merge/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_merge/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -74,7 +75,7 @@ struct instantiator { { // Validate range overload, empty range1 P output[size(elements2)]{}; - R1 range1{}; + R1 range1{span{}}; R2 range2{elements2}; size_t counter = 0; @@ -89,7 +90,7 @@ struct instantiator { { // Validate iterator overload, empty range2 P output[size(elements1)]{}; R1 range1{elements1}; - R2 range2{}; + R2 range2{span{}}; size_t counter = 0; const same_as, iterator_t, O>> auto result = diff --git a/tests/std/tests/P0896R4_ranges_alg_minmax/test.cpp b/tests/std/tests/P0896R4_ranges_alg_minmax/test.cpp index e76461db2e2..4d690675bb8 100644 --- a/tests/std/tests/P0896R4_ranges_alg_minmax/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_minmax/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,7 @@ struct mm_element_empty { template static constexpr void call() { // Validate empty ranges - const Fwd range{}; + const Fwd range{span{}}; ASSERT(ranges::min_element(range, ranges::less{}, get_first) == ranges::end(range)); ASSERT(ranges::min_element(ranges::begin(range), ranges::end(range), ranges::less{}, get_first) diff --git a/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp b/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp index 2ee68e9a70b..c59698a84f5 100644 --- a/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_mismatch/test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -78,9 +79,12 @@ int main() { #ifndef _PREFAST_ // TRANSITION, GH-1030 struct instantiator { template - static void call(In1&& in1 = {}, In2&& in2 = {}) { + static void call() { using ranges::begin, ranges::end, ranges::mismatch, ranges::iterator_t; + In1 in1{std::span{}}; + In2 in2{std::span{}}; + if constexpr (!is_permissive) { (void) mismatch(in1, in2); (void) mismatch(begin(in1), end(in1), begin(in2), end(in2)); diff --git a/tests/std/tests/P0896R4_ranges_alg_nth_element/test.cpp b/tests/std/tests/P0896R4_ranges_alg_nth_element/test.cpp index 8d34d35fc8f..b9251e1bd47 100644 --- a/tests/std/tests/P0896R4_ranges_alg_nth_element/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_nth_element/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -63,7 +64,7 @@ struct instantiator { { // Validate empty range - const R range{}; + const R range{span{}}; const same_as> auto result = nth_element(range, range.begin(), less{}, get_first); assert(result == range.end()); } diff --git a/tests/std/tests/P0896R4_ranges_alg_partial_sort_copy/test.cpp b/tests/std/tests/P0896R4_ranges_alg_partial_sort_copy/test.cpp index e7ba82b960a..505269ea183 100644 --- a/tests/std/tests/P0896R4_ranges_alg_partial_sort_copy/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_partial_sort_copy/test.cpp @@ -52,7 +52,7 @@ struct instantiator1 { } // also with empty input - In range1{}; + In range1{span{}}; Out range2{output}; const same_as, iterator_t>> auto result = partial_sort_copy(range1, range2, less{}, get_first, get_first); @@ -85,7 +85,7 @@ struct instantiator2 { } // also with empty input - In range1{}; + In range1{span{}}; Out range2{output}; const same_as, iterator_t>> auto result = partial_sort_copy( range1.begin(), range1.end(), range2.begin(), range2.end(), less{}, get_first, get_first); diff --git a/tests/std/tests/P0896R4_ranges_alg_partition/test.cpp b/tests/std/tests/P0896R4_ranges_alg_partition/test.cpp index 01bff413f27..f7cfcf5faf6 100644 --- a/tests/std/tests/P0896R4_ranges_alg_partition/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_partition/test.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -31,16 +32,16 @@ struct empty_test { // Validate empty ranges using ranges::is_partitioned, ranges::partition, ranges::partition_point; { - Range range{}; + Range range{span{}}; ASSERT(is_partitioned(range, is_even, get_first)); } { - Range range{}; + Range range{span{}}; ASSERT(is_partitioned(range.begin(), range.end(), is_even, get_first)); } if constexpr (ranges::forward_range) { - const Range range{}; + const Range range{span{}}; { const auto result = partition(range, is_even, get_first); ASSERT(result.begin() == range.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_partition_copy/test.cpp b/tests/std/tests/P0896R4_ranges_alg_partition_copy/test.cpp index 12d3d4cbd86..199003f1f61 100644 --- a/tests/std/tests/P0896R4_ranges_alg_partition_copy/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_partition_copy/test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -37,20 +38,17 @@ struct empty_test { using ranges::partition_copy, ranges::partition_copy_result, ranges::iterator_t; { - Range range{}; - auto result = partition_copy(range, Out1{}, Out2{}, is_even, get_first); - STATIC_ASSERT(same_as, Out1, Out2>>); + Range range{span{}}; + same_as, Out1, Out2>> auto result = + partition_copy(range, Out1{nullptr}, Out2{nullptr}, is_even, get_first); ASSERT(result.in == range.end()); ASSERT(result.out1.peek() == nullptr); ASSERT(result.out2.peek() == nullptr); } { - Range range{}; - auto result = partition_copy(range.begin(), range.end(), Out1{}, Out2{}, is_even, get_first); - STATIC_ASSERT( - same_as, Out1, Out2>>); + Range range{span{}}; + same_as, Out1, Out2>> auto result = + partition_copy(range.begin(), range.end(), Out1{nullptr}, Out2{nullptr}, is_even, get_first); ASSERT(result.in == range.end()); ASSERT(result.out1.peek() == nullptr); ASSERT(result.out2.peek() == nullptr); diff --git a/tests/std/tests/P0896R4_ranges_alg_partition_point/test.cpp b/tests/std/tests/P0896R4_ranges_alg_partition_point/test.cpp index bfd99511fae..a56b194e709 100644 --- a/tests/std/tests/P0896R4_ranges_alg_partition_point/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_partition_point/test.cpp @@ -30,7 +30,7 @@ struct empty_test { // Validate empty ranges using ranges::partition_point; - const Range range{}; + const Range range{span{}}; ASSERT(partition_point(range, is_even, get_first) == range.end()); ASSERT(partition_point(range.begin(), range.end(), is_even, get_first) == range.end()); } diff --git a/tests/std/tests/P0896R4_ranges_alg_permutations/test.cpp b/tests/std/tests/P0896R4_ranges_alg_permutations/test.cpp index c169e8212fa..af7f976843e 100644 --- a/tests/std/tests/P0896R4_ranges_alg_permutations/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_permutations/test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -202,7 +203,7 @@ struct empty_range_test { ranges::prev_permutation_result, ranges::iterator_t; { // Validate range overload, next_permutation - R range{}; + R range{span{}}; const same_as>> auto result = next_permutation(range, ranges::less{}, get_val); assert(result.in == range.end()); @@ -210,7 +211,7 @@ struct empty_range_test { } { // Validate iterator overload, next_permutation - R range{}; + R range{span{}}; const same_as>> auto result = next_permutation(range.begin(), range.end(), ranges::less{}, get_val); assert(result.in == range.end()); @@ -218,7 +219,7 @@ struct empty_range_test { } { // Validate range overload, prev_permutation - R range{}; + R range{span{}}; const same_as>> auto result = prev_permutation(range, ranges::less{}, get_val); assert(result.in == range.end()); @@ -226,7 +227,7 @@ struct empty_range_test { } { // Validate iterator overload, prev_permutation - R range{}; + R range{span{}}; const same_as>> auto result = prev_permutation(range.begin(), range.end(), ranges::less{}, get_val); assert(result.in == range.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_reverse/test.cpp b/tests/std/tests/P0896R4_ranges_alg_reverse/test.cpp index 11b78e69cc6..773005a4a29 100644 --- a/tests/std/tests/P0896R4_ranges_alg_reverse/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_reverse/test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -71,13 +72,13 @@ struct instantiator { assert(equal(input, expected_even)); } { // Validate iterator + sentinel overload, empty range - R wrapped_input{}; + R wrapped_input{span{}}; auto result = reverse(wrapped_input.begin(), wrapped_input.end()); STATIC_ASSERT(same_as>); assert(result == wrapped_input.end()); } { // Validate range overload, empty range - R wrapped_input{}; + R wrapped_input{span{}}; auto result = reverse(wrapped_input); STATIC_ASSERT(same_as>); assert(result == wrapped_input.end()); @@ -136,13 +137,13 @@ struct test_vector { } { // Validate iterator + sentinel overload, vectorizable empty - R wrapped_input{}; + R wrapped_input{span, 0>{}}; auto result = reverse(wrapped_input.begin(), wrapped_input.end()); STATIC_ASSERT(same_as>); assert(result == wrapped_input.end()); } { // Validate range overload, vectorizable empty - R wrapped_input{}; + R wrapped_input{span, 0>{}}; auto result = reverse(wrapped_input); STATIC_ASSERT(same_as>); assert(result == wrapped_input.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_reverse_copy/test.cpp b/tests/std/tests/P0896R4_ranges_alg_reverse_copy/test.cpp index f991ab70765..152f4409618 100644 --- a/tests/std/tests/P0896R4_ranges_alg_reverse_copy/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_reverse_copy/test.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -66,7 +67,7 @@ struct instantiator { { // Validate iterator overload, empty range nontrivial_int output[3]; - In wrapped_input{}; + In wrapped_input{span{}}; const same_as, Out>> auto result = reverse_copy(wrapped_input.begin(), wrapped_input.end(), Out{output}); assert(result.in == wrapped_input.end()); @@ -74,7 +75,7 @@ struct instantiator { } { // Validate range overload, empty range nontrivial_int output[3]; - In wrapped_input{}; + In wrapped_input{span{}}; const same_as, Out>> auto result = reverse_copy(wrapped_input, Out{output}); assert(result.in == wrapped_input.end()); @@ -129,7 +130,7 @@ struct test_vector { { // Validate iterator overload, vectorizable empty range_value_t output[3]; - In wrapped_input{}; + In wrapped_input{span, 0>{}}; const same_as, Out>> auto result = reverse_copy(wrapped_input.begin(), wrapped_input.end(), Out{output}); assert(result.in == wrapped_input.end()); @@ -137,7 +138,7 @@ struct test_vector { } { // Validate range overload, vectorizable empty range_value_t output[3]; - In wrapped_input{}; + In wrapped_input{span, 0>{}}; const same_as, Out>> auto result = reverse_copy(wrapped_input, Out{output}); assert(result.in == wrapped_input.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_set_difference/test.cpp b/tests/std/tests/P0896R4_ranges_alg_set_difference/test.cpp index 6332bd4d468..c0fc9006b0e 100644 --- a/tests/std/tests/P0896R4_ranges_alg_set_difference/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_set_difference/test.cpp @@ -58,7 +58,7 @@ struct instantiator { { // Validate range overload, empty range1 P output[osize]{}; - R1 range1{}; + R1 range1{span{}}; R2 range2{elements2}; const same_as, O>> auto result = set_difference(range1, range2, O{output}, ranges::less{}, get_first, get_second); @@ -68,7 +68,7 @@ struct instantiator { { // Validate iterator overload, empty range2 P output[osize]{}; R1 range1{elements1}; - R2 range2{}; + R2 range2{span{}}; const same_as, O>> auto result = set_difference(range1.begin(), range1.end(), range2.begin(), range2.end(), O{output}, ranges::less{}, get_first, get_second); assert(result.in == range1.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_set_intersection/test.cpp b/tests/std/tests/P0896R4_ranges_alg_set_intersection/test.cpp index ee621df8a6c..65c36fe0303 100644 --- a/tests/std/tests/P0896R4_ranges_alg_set_intersection/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_set_intersection/test.cpp @@ -69,7 +69,7 @@ struct instantiator { { // Validate range overload, empty range1 P output[osize]{}; - R1 range1{}; + R1 range1{span{}}; R2 range2{elements2}; const same_as, iterator_t, O>> auto result = set_intersection(range1, range2, O{output}, ranges::less{}, get_first, get_second); @@ -80,7 +80,7 @@ struct instantiator { { // Validate iterator overload, empty range2 P output[osize]{}; R1 range1{elements1}; - R2 range2{}; + R2 range2{span{}}; const same_as, iterator_t, O>> auto result = set_intersection(range1.begin(), range1.end(), range2.begin(), range2.end(), O{output}, ranges::less{}, get_first, get_second); diff --git a/tests/std/tests/P0896R4_ranges_alg_set_symmetric_difference/test.cpp b/tests/std/tests/P0896R4_ranges_alg_set_symmetric_difference/test.cpp index d2e82ce92ea..660e4e6c08d 100644 --- a/tests/std/tests/P0896R4_ranges_alg_set_symmetric_difference/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_set_symmetric_difference/test.cpp @@ -69,7 +69,7 @@ struct instantiator { { // Validate range overload, empty range1 P output[osize]{}; - R1 range1{}; + R1 range1{span{}}; R2 range2{elements2}; const same_as, iterator_t, O>> auto result = set_symmetric_difference(range1, range2, O{output}, ranges::less{}, get_first, get_second); @@ -81,7 +81,7 @@ struct instantiator { { // Validate iterator overload, empty range2 P output[osize]{}; R1 range1{elements1}; - R2 range2{}; + R2 range2{span{}}; const same_as, iterator_t, O>> auto result = set_symmetric_difference(range1.begin(), range1.end(), range2.begin(), range2.end(), O{output}, ranges::less{}, get_first, get_second); diff --git a/tests/std/tests/P0896R4_ranges_alg_set_union/test.cpp b/tests/std/tests/P0896R4_ranges_alg_set_union/test.cpp index 3ab9116cfd9..2cae9615766 100644 --- a/tests/std/tests/P0896R4_ranges_alg_set_union/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_set_union/test.cpp @@ -66,7 +66,7 @@ struct instantiator { { // Validate range overload, empty range1 P output[osize]{}; - R1 range1{}; + R1 range1{span{}}; R2 range2{elements2}; const same_as, iterator_t, O>> auto result = set_union(range1, range2, O{output}, ranges::less{}, get_first, get_second); @@ -78,7 +78,7 @@ struct instantiator { { // Validate iterator overload, empty range2 P output[osize]{}; R1 range1{elements1}; - R2 range2{}; + R2 range2{span{}}; const same_as, iterator_t, O>> auto result = set_union(range1.begin(), range1.end(), range2.begin(), range2.end(), O{output}, ranges::less{}, get_first, get_second); assert(result.in1 == range1.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp b/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp index 8c01b10ec60..909e496fccd 100644 --- a/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_sort/test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,7 @@ struct instantiator { } { // Validate empty range - const R range{}; + const R range{span{}}; const same_as> auto result = sort(range, less{}, get_first); assert(result == range.end()); assert(is_sorted(range, less{}, get_first)); diff --git a/tests/std/tests/P0896R4_ranges_alg_stable_partition/test.cpp b/tests/std/tests/P0896R4_ranges_alg_stable_partition/test.cpp index cc9cd58ee15..9657819f685 100644 --- a/tests/std/tests/P0896R4_ranges_alg_stable_partition/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_stable_partition/test.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -34,7 +35,7 @@ struct instantiator { assert(is_sorted(range)); // Validate empty range - const Range empty_range{}; + const Range empty_range{span{}}; const same_as>> auto empty_result = stable_partition(empty_range, is_even, get_first); assert(empty_result.begin() == empty_range.end()); @@ -53,7 +54,7 @@ struct instantiator { assert(is_sorted(range)); // Validate empty range - const Range empty_range{}; + const Range empty_range{span{}}; const same_as>> auto empty_result = stable_partition(empty_range.begin(), empty_range.end(), is_even, get_first); assert(empty_result.begin() == empty_range.end()); diff --git a/tests/std/tests/P0896R4_ranges_alg_stable_sort/test.cpp b/tests/std/tests/P0896R4_ranges_alg_stable_sort/test.cpp index f20095aa55b..f3eb84597d9 100644 --- a/tests/std/tests/P0896R4_ranges_alg_stable_sort/test.cpp +++ b/tests/std/tests/P0896R4_ranges_alg_stable_sort/test.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,7 @@ struct instantiator { } { // Validate empty range - const R range{}; + const R range{span{}}; const same_as> auto result = stable_sort(range, less{}, get_first); assert(result == range.end()); assert(is_sorted(range, less{})); diff --git a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp index 9429d072929..bf7f9fe8c0f 100644 --- a/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp +++ b/tests/std/tests/P0896R4_ranges_iterator_machinery/test.cpp @@ -138,6 +138,8 @@ struct simple_input_iter { using value_type = double; using difference_type = long; + explicit simple_input_iter(int); // not default constructible + value_type operator*() const; simple_input_iter& operator++(); simple_input_iter operator++(int); @@ -306,18 +308,18 @@ struct destructible_archetype<0> { inline constexpr std::size_t destructible_archetype_max = 1; // clang-format off -#define SEMIREGULAR_OPS(prefix) \ - prefix##_archetype() requires (I != 1); \ - prefix##_archetype(prefix##_archetype const&) requires (I != 2); \ - prefix##_archetype(prefix##_archetype&&) requires (I == 3) = delete; \ +#define COPYABLE_OPS(prefix) \ + prefix##_archetype(prefix##_archetype const&) requires (I != 1); \ + prefix##_archetype(prefix##_archetype&&) requires (I == 2) = delete; \ \ - prefix##_archetype& operator=(prefix##_archetype const&) requires (I != 4); \ - prefix##_archetype& operator=(prefix##_archetype&&) requires (I == 5) = delete + prefix##_archetype& operator=(prefix##_archetype const&) requires (I != 3); \ + prefix##_archetype& operator=(prefix##_archetype&&) requires (I == 4) = delete // clang-format on template struct semiregular_archetype : destructible_archetype { - SEMIREGULAR_OPS(semiregular); + semiregular_archetype() requires(I != 5); + COPYABLE_OPS(semiregular); }; inline constexpr std::size_t semiregular_archetype_max = 6; @@ -327,23 +329,23 @@ struct weakly_incrementable_archetype_dt { using difference_type = int; }; template <> -struct weakly_incrementable_archetype_dt<6> {}; +struct weakly_incrementable_archetype_dt<5> {}; template <> -struct weakly_incrementable_archetype_dt<7> { +struct weakly_incrementable_archetype_dt<6> { using difference_type = void; }; template <> -struct weakly_incrementable_archetype_dt<8> { +struct weakly_incrementable_archetype_dt<7> { using difference_type = unsigned int; }; template struct increment_ops { // clang-format off - void operator++() requires (I == 9); - Derived operator++() requires (I == 10); - Derived& operator++() requires (I < 9 || I >= 11); - Post operator++(int) requires (I != 11); + void operator++() requires (I == 8); + Derived operator++() requires (I == 9); + Derived& operator++() requires (I < 8 || I >= 10); + Post operator++(int) requires (I != 10); // clang-format on }; @@ -352,27 +354,27 @@ struct weakly_incrementable_archetype : destructible_archetype, weakly_incrementable_archetype_dt, increment_ops, void> { // clang-format off - weakly_incrementable_archetype() requires (I != 1) {} weakly_incrementable_archetype(weakly_incrementable_archetype const&) = delete; - weakly_incrementable_archetype(weakly_incrementable_archetype&&) requires (I < 2 || I >= 4) = default; + weakly_incrementable_archetype(weakly_incrementable_archetype&&) requires (I < 1 || I >= 3) = default; weakly_incrementable_archetype& operator=(weakly_incrementable_archetype const&) = delete; - weakly_incrementable_archetype& operator=(weakly_incrementable_archetype&&) requires (I < 4 || I >= 6) = default; + weakly_incrementable_archetype& operator=(weakly_incrementable_archetype&&) requires (I < 3 || I >= 5) = default; // clang-format on }; -inline constexpr std::size_t weakly_incrementable_archetype_max = 12; +inline constexpr std::size_t weakly_incrementable_archetype_max = 11; template struct incrementable_archetype : weakly_incrementable_archetype, increment_ops, incrementable_archetype> { - SEMIREGULAR_OPS(incrementable); + incrementable_archetype() requires(I != 11); + COPYABLE_OPS(incrementable); using increment_ops, incrementable_archetype>::operator++; // clang-format off - bool operator==(incrementable_archetype const&) const requires (I != weakly_incrementable_archetype_max); + bool operator==(incrementable_archetype const&) const requires (I != 12); bool operator!=(incrementable_archetype const&) const - requires (I == weakly_incrementable_archetype_max + 1) = delete; + requires (I == 13) = delete; // clang-format on }; @@ -380,22 +382,23 @@ inline constexpr std::size_t incrementable_archetype_max = 14; template struct iterator_archetype : weakly_incrementable_archetype { - SEMIREGULAR_OPS(iterator); + COPYABLE_OPS(iterator); // clang-format off - iterator_archetype& operator++() requires (I > 10); - void operator++(int) requires (I != 11); + iterator_archetype& operator++() requires (I > 9); + void operator++(int) requires (I != 10); - void operator*() requires (I == 12); - int operator*() requires (I != 12); + void operator*() requires (I == 11); + int operator*() requires (I != 11); // clang-format on }; -inline constexpr std::size_t iterator_archetype_max = 13; +inline constexpr std::size_t iterator_archetype_max = 12; template struct sentinel_archetype : semiregular_archetype { - SEMIREGULAR_OPS(sentinel); + sentinel_archetype() requires(I != 5); + COPYABLE_OPS(sentinel); // clang-format off template @@ -408,7 +411,8 @@ inline constexpr std::size_t sentinel_archetype_max = 7; template struct sized_sentinel_archetype : sentinel_archetype { - SEMIREGULAR_OPS(sized_sentinel); + sized_sentinel_archetype() requires(I != 5); + COPYABLE_OPS(sized_sentinel); }; // clang-format off @@ -439,38 +443,38 @@ inline constexpr std::size_t sized_sentinel_archetype_max = 12; template struct output_iterator_archetype : iterator_archetype, increment_ops, output_iterator_archetype&> { - SEMIREGULAR_OPS(output_iterator); + COPYABLE_OPS(output_iterator); using increment_ops, output_iterator_archetype&>::operator++; // clang-format off // dereference ops from iterator_archetype - void operator*() requires (I == 12); - output_iterator_archetype& operator*() requires (I != 12); + void operator*() requires (I == 11); + output_iterator_archetype& operator*() requires (I != 11); // indirectly_writable requirements - void operator=(int) requires (I != 13); + void operator=(int) requires (I != 12); // clang-format on }; -inline constexpr std::size_t output_iterator_archetype_max = 14; +inline constexpr std::size_t output_iterator_archetype_max = 13; template struct input_iterator_archetype_types { using value_type = int; }; template <> -struct input_iterator_archetype_types<13> {}; +struct input_iterator_archetype_types<12> {}; template <> -struct input_iterator_archetype_types<14> { +struct input_iterator_archetype_types<13> { using value_type = void; }; template <> -struct input_iterator_archetype_types<15> { +struct input_iterator_archetype_types<14> { using iterator_category = void; using value_type = int; }; template <> -struct input_iterator_archetype_types<16> { +struct input_iterator_archetype_types<15> { using iterator_concept = void; using value_type = int; }; @@ -479,27 +483,28 @@ template struct input_iterator_archetype : iterator_archetype, input_iterator_archetype_types, increment_ops, void> { - SEMIREGULAR_OPS(input_iterator); + COPYABLE_OPS(input_iterator); using increment_ops, void>::operator++; // clang-format off // dereference ops from iterator_archetype - void operator*() const requires (I == 12); - int& operator*() const requires (I != 12); + void operator*() const requires (I == 11); + int& operator*() const requires (I != 11); // clang-format on }; -inline constexpr std::size_t input_iterator_archetype_max = 17; +inline constexpr std::size_t input_iterator_archetype_max = 16; template struct forward_iterator_archetype : input_iterator_archetype, increment_ops, forward_iterator_archetype> { - SEMIREGULAR_OPS(forward_iterator); + forward_iterator_archetype() requires(I != 16); + COPYABLE_OPS(forward_iterator); using increment_ops, forward_iterator_archetype>::operator++; // clang-format off - bool operator==(forward_iterator_archetype const&) const requires (I != input_iterator_archetype_max); - bool operator!=(forward_iterator_archetype const&) const requires (I == input_iterator_archetype_max + 1) = delete; + bool operator==(forward_iterator_archetype const&) const requires (I != 17); + bool operator!=(forward_iterator_archetype const&) const requires (I == 18) = delete; // clang-format on }; @@ -519,7 +524,8 @@ template struct bidi_iterator_archetype : forward_iterator_archetype, increment_ops, bidi_iterator_archetype>, decrement_ops> { - SEMIREGULAR_OPS(bidi_iterator); + bidi_iterator_archetype() requires(I != 16); + COPYABLE_OPS(bidi_iterator); using increment_ops, bidi_iterator_archetype>::operator++; }; @@ -529,14 +535,15 @@ template struct random_iterator_archetype : bidi_iterator_archetype, increment_ops, random_iterator_archetype>, decrement_ops> { - SEMIREGULAR_OPS(random_iterator); + random_iterator_archetype() requires(I != 16); + COPYABLE_OPS(random_iterator); using increment_ops, random_iterator_archetype>::operator++; using decrement_ops>::operator--; // clang-format off std::strong_ordering operator<=>(random_iterator_archetype const&) const requires (I != 22); - int operator-(random_iterator_archetype const&) const requires (I != 6 && I != 23); + int operator-(random_iterator_archetype const&) const requires (I != 5 && I != 23); random_iterator_archetype& operator+=(int) requires (I != 24); random_iterator_archetype operator+(int) const requires (I != 25); @@ -560,7 +567,7 @@ struct contig_iterator_archetype_types : random_iterator_archetype { }; // clang-format off template - requires (I == 15 || I == 16 || I == 31) + requires (I == 14 || I == 15 || I == 31) struct contig_iterator_archetype_types : random_iterator_archetype {}; // clang-format on template <> @@ -577,12 +584,13 @@ template struct contig_iterator_archetype : increment_ops, contig_iterator_archetype>, decrement_ops>, contig_iterator_archetype_types { - SEMIREGULAR_OPS(contig_iterator); + contig_iterator_archetype() requires(I != 16); + COPYABLE_OPS(contig_iterator); using increment_ops, contig_iterator_archetype>::operator++; using decrement_ops>::operator--; // clang-format off - int operator-(contig_iterator_archetype const&) const requires (I != 6 && I != 23); + int operator-(contig_iterator_archetype const&) const requires (I != 5 && I != 23); contig_iterator_archetype& operator+=(int) requires (I != 24); contig_iterator_archetype operator+(int) const requires (I != 25); @@ -2912,14 +2920,8 @@ namespace insert_iterators { template constexpr bool test() { using std::back_insert_iterator, std::front_insert_iterator, std::insert_iterator; - using std::default_initializable, std::is_nothrow_default_constructible_v, std::iter_difference_t, - std::ptrdiff_t, std::same_as; - - STATIC_ASSERT(default_initializable>); - STATIC_ASSERT(is_nothrow_default_constructible_v>); - STATIC_ASSERT(default_initializable>); - STATIC_ASSERT(is_nothrow_default_constructible_v>); - STATIC_ASSERT(default_initializable>); + using std::iter_difference_t, std::ptrdiff_t, std::same_as; + STATIC_ASSERT(same_as>, ptrdiff_t>); STATIC_ASSERT(same_as>, ptrdiff_t>); STATIC_ASSERT(same_as>, ptrdiff_t>); @@ -2929,6 +2931,35 @@ namespace insert_iterators { STATIC_ASSERT(test>()); STATIC_ASSERT(test>()); + + struct container { + using value_type = int; + + constexpr int* begin() { + return &value; + } + constexpr int* end() { + return &value + 1; + } + constexpr int* insert(int* ptr, int i) { + assert(ptr == &value); + value = i; + return &value; + } + + int value; + }; + + constexpr bool test_insert_relaxation() { + // Verify that insert_iterator correctly does not require a nested `iterator` typename + container c; + std::insert_iterator i(c, c.begin()); + *i = 42; + assert(c.value == 42); + return true; + } + + STATIC_ASSERT(test_insert_relaxation()); } // namespace insert_iterators namespace reverse_iterator_test { @@ -3276,8 +3307,8 @@ namespace counted_iterator_test { same_as>>::iterator_category, forward_iterator_tag>); STATIC_ASSERT(same_as>::iterator_category, input_iterator_tag>); - // Validate that postincrement returns counted_iterator for single-pass adaptees - STATIC_ASSERT(same_as {} ++), counted_iterator>); + // Validate postincrement + STATIC_ASSERT(same_as&>()++), simple_input_iter>); STATIC_ASSERT( same_as> {} ++), counted_iterator>>); diff --git a/tests/std/tests/P0896R4_ranges_ref_view/test.cpp b/tests/std/tests/P0896R4_ranges_ref_view/test.cpp index 0a69e1e5561..1105f717aa8 100644 --- a/tests/std/tests/P0896R4_ranges_ref_view/test.cpp +++ b/tests/std/tests/P0896R4_ranges_ref_view/test.cpp @@ -35,9 +35,6 @@ struct instantiator { { // constructors and assignment operators STATIC_ASSERT(!constructible_from, R>); - ref_view default_constructed{}; - STATIC_ASSERT(is_nothrow_default_constructible_v>); - R wrapped_input{input}; ref_view same_range{wrapped_input}; STATIC_ASSERT(is_nothrow_constructible_v, R&>); @@ -48,13 +45,16 @@ struct instantiator { } assert(copy_constructed.end().peek() == end(input)); - default_constructed = copy_constructed; + int other_data[3] = {4, 5, 6}; + R wrapped_other{other_data}; + ref_view copy_assigned{wrapped_other}; + copy_assigned = copy_constructed; if constexpr (forward_range) { - assert(default_constructed.begin().peek() == begin(input)); + assert(copy_assigned.begin().peek() == begin(input)); } - assert(default_constructed.end().peek() == end(input)); + assert(copy_assigned.end().peek() == end(input)); - [[maybe_unused]] auto move_constructed = std::move(default_constructed); + [[maybe_unused]] auto move_constructed = std::move(copy_assigned); if constexpr (forward_range) { assert(move_constructed.begin().peek() == begin(input)); } @@ -121,7 +121,7 @@ struct instantiator { STATIC_ASSERT(noexcept(as_const(test_view).empty()) == noexcept(ranges::empty(wrapped_input))); - R empty_range{}; + R empty_range{span{}}; ref_view empty_view{empty_range}; assert(empty_view.empty()); } diff --git a/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp b/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp index d3e67fbcc01..8bf8494afff 100644 --- a/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp +++ b/tests/std/tests/P0896R4_ranges_subrange/test.compile.pass.cpp @@ -815,7 +815,7 @@ namespace test_subrange { using size_type = std::make_unsigned_t>; // Validate SMFs - STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable == default_initializable); STATIC_ASSERT(movable); STATIC_ASSERT(!copyable || copyable); diff --git a/tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp b/tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp index e761386399a..276b703c5c8 100644 --- a/tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp +++ b/tests/std/tests/P0896R4_ranges_test_machinery/test.compile.pass.cpp @@ -21,7 +21,7 @@ constexpr bool iter_test() { using I = iterator; - STATIC_ASSERT(default_initializable); + STATIC_ASSERT(default_initializable == (Eq == CanCompare::yes)); STATIC_ASSERT(movable); STATIC_ASSERT(!movable || indirectly_writable); diff --git a/tests/std/tests/P0896R4_stream_iterators/test.cpp b/tests/std/tests/P0896R4_stream_iterators/test.cpp index e41a74fdb1d..0ca401f8ee0 100644 --- a/tests/std/tests/P0896R4_stream_iterators/test.cpp +++ b/tests/std/tests/P0896R4_stream_iterators/test.cpp @@ -63,10 +63,7 @@ void test_ostream_iterator(basic_ostream& os) { #ifdef __cpp_lib_concepts STATIC_ASSERT(output_iterator); - STATIC_ASSERT(is_same_v); - { [[maybe_unused]] constexpr I constexprConstructed{}; } - STATIC_ASSERT(is_nothrow_default_constructible_v); #endif // __cpp_lib_concepts } @@ -100,10 +97,7 @@ void test_ostreambuf_iterator(basic_ostream& os) { #ifdef __cpp_lib_concepts STATIC_ASSERT(output_iterator); - STATIC_ASSERT(is_same_v); - { [[maybe_unused]] constexpr I constexprConstructed{}; } - STATIC_ASSERT(is_nothrow_default_constructible_v); #endif // __cpp_lib_concepts } diff --git a/tests/std/tests/P0896R4_views_all/test.cpp b/tests/std/tests/P0896R4_views_all/test.cpp index c2450d1e47d..fff8c7f586f 100644 --- a/tests/std/tests/P0896R4_views_all/test.cpp +++ b/tests/std/tests/P0896R4_views_all/test.cpp @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include @@ -208,11 +207,4 @@ int main() { 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_drop/test.cpp b/tests/std/tests/P0896R4_views_drop/test.cpp index 41119f7e2d4..165f82c8756 100644 --- a/tests/std/tests/P0896R4_views_drop/test.cpp +++ b/tests/std/tests/P0896R4_views_drop/test.cpp @@ -399,7 +399,7 @@ struct instantiator { R r{some_ints}; test_one(r, only_four_ints); - R empty_range{}; + R empty_range{span{}}; test_one(empty_range, span{}); } }; @@ -533,11 +533,6 @@ int main() { instantiation_test(); { - // Validate a non-view borrowed range - constexpr span s{some_ints}; - STATIC_ASSERT(test_one(s, only_four_ints)); - test_one(s, only_four_ints); - // Validate a view borrowed range constexpr auto v = views::iota(0ull, ranges::size(some_ints)) | views::transform([](auto i) { return some_ints[i]; }); diff --git a/tests/std/tests/P0896R4_views_drop_while/test.cpp b/tests/std/tests/P0896R4_views_drop_while/test.cpp index fe36b6b11cd..2868e9d01f9 100644 --- a/tests/std/tests/P0896R4_views_drop_while/test.cpp +++ b/tests/std/tests/P0896R4_views_drop_while/test.cpp @@ -373,13 +373,6 @@ int main() { test_one(lst, expected_output); } - // Validate a non-view borrowed range - { - constexpr span s{some_ints}; - STATIC_ASSERT(test_one(s, expected_output)); - test_one(s, expected_output); - } - // drop_while/reverse interaction test { auto dwr_pipe = views::drop_while(is_less_than<3>) | views::reverse; diff --git a/tests/std/tests/P0896R4_views_drop_while_death/test.cpp b/tests/std/tests/P0896R4_views_drop_while_death/test.cpp index 216fefc6633..9cce078838d 100644 --- a/tests/std/tests/P0896R4_views_drop_while_death/test.cpp +++ b/tests/std/tests/P0896R4_views_drop_while_death/test.cpp @@ -11,16 +11,37 @@ #include using namespace std; -[[maybe_unused]] constexpr auto lambda = [x = 42](int) { return x == 42; }; -using DWV = decltype(ranges::drop_while_view{span{}, lambda}); +struct test_predicate { + struct tag {}; + + test_predicate() = default; + test_predicate(const test_predicate&) { + throw tag{}; + } + test_predicate& operator=(const test_predicate&) = delete; + + constexpr bool operator()(int i) const { + return i == 42; + } +}; + +auto with_no_predicate() { + using DWV = decltype(ranges::drop_while_view{span{}, test_predicate{}}); + DWV r; + try { + r = DWV{}; + } catch (const test_predicate::tag&) { + } + return r; +} void test_view_predicate() { - DWV r; - (void) r.pred(); // value-initialized drop_while_view has no predicate + auto r = with_no_predicate(); + (void) r.pred(); // drop_while_view has no predicate } void test_view_begin() { - DWV r; + auto r = with_no_predicate(); (void) r.begin(); // N4885 [range.drop.while.view] forbids calling begin on a drop_while_view with no predicate } diff --git a/tests/std/tests/P0896R4_views_elements/test.cpp b/tests/std/tests/P0896R4_views_elements/test.cpp index f1ee7dcec74..3461012a7c1 100644 --- a/tests/std/tests/P0896R4_views_elements/test.cpp +++ b/tests/std/tests/P0896R4_views_elements/test.cpp @@ -411,12 +411,6 @@ int main() { instantiation_test(); } - { // Validate a non-view borrowed range - constexpr span s{some_pairs}; - STATIC_ASSERT(test_one(s)); - test_one(s); - } - { // Validate a view borrowed range constexpr auto v = views::iota(0ull, ranges::size(expected_keys)) | views::transform([](auto i) { return make_pair(expected_keys[i], expected_values[i]); }); diff --git a/tests/std/tests/P0896R4_views_filter/test.cpp b/tests/std/tests/P0896R4_views_filter/test.cpp index 48572a89c82..ba92e730789 100644 --- a/tests/std/tests/P0896R4_views_filter/test.cpp +++ b/tests/std/tests/P0896R4_views_filter/test.cpp @@ -347,13 +347,6 @@ int main() { test_one(lst, only_even_ints); } - // Validate a non-view borrowed range - { - constexpr span s{some_ints}; - STATIC_ASSERT(test_one(s, only_even_ints)); - test_one(s, only_even_ints); - } - // filter/reverse interaction test { auto fr_pipe = views::filter(is_even) | views::reverse; diff --git a/tests/std/tests/P0896R4_views_filter_death/test.cpp b/tests/std/tests/P0896R4_views_filter_death/test.cpp index d784bedca19..6a79aa699af 100644 --- a/tests/std/tests/P0896R4_views_filter_death/test.cpp +++ b/tests/std/tests/P0896R4_views_filter_death/test.cpp @@ -13,19 +13,43 @@ using namespace std; static int some_ints[] = {0, 1, 2, 3}; -[[maybe_unused]] constexpr auto lambda = [x = 42](int) { return x == 42; }; -using FV = decltype(ranges::filter_view{some_ints, lambda}); +struct test_predicate { + struct tag {}; + + test_predicate() = default; + test_predicate(const test_predicate&) { + throw tag{}; + } + test_predicate& operator=(const test_predicate&) = delete; + + constexpr bool operator()(int i) const { + return i == 42; + } +}; + +auto with_no_predicate() { + using V = decltype(ranges::filter_view{some_ints, test_predicate{}}); + V r{some_ints, {}}; + try { + r = V{some_ints, {}}; + } catch (const test_predicate::tag&) { + } + return r; +} void test_view_predicate() { - FV r; - (void) r.pred(); // value-initialized filter_view has no predicate + auto r = with_no_predicate(); + (void) r.pred(); // filter_view has no predicate } void test_view_begin() { - FV r; + auto r = with_no_predicate(); (void) r.begin(); // N4861 [range.filter.view]/3 forbids calling begin on a filter_view that holds no predicate } +constexpr auto lambda = [x = 42](int) { return x == 42; }; +using FV = decltype(ranges::filter_view{some_ints, lambda}); + void test_constructor_wrong_range() { vector vec0{0, 1, 2, 3}; vector vec1{4, 5, 6, 7}; diff --git a/tests/std/tests/P0896R4_views_join/test.cpp b/tests/std/tests/P0896R4_views_join/test.cpp index cd989531f13..777c16502f3 100644 --- a/tests/std/tests/P0896R4_views_join/test.cpp +++ b/tests/std/tests/P0896R4_views_join/test.cpp @@ -50,7 +50,7 @@ constexpr bool test_one(Outer&& rng, Expected&& expected) { static_assert(!ranges::random_access_range); static_assert(!ranges::contiguous_range); - constexpr bool is_view = ranges::view; + constexpr bool is_view = ranges::view>; // Validate range adapter object // ...with lvalue argument @@ -132,7 +132,12 @@ constexpr bool test_one(Outer&& rng, Expected&& expected) { // Validate deduction guide same_as auto r = join_view{forward(rng)}; - assert(ranges::equal(r, expected)); +#ifndef __cpp_lib_constexpr_dynamic_alloc + if (!is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { + assert(ranges::equal(r, expected)); + } const bool is_empty = ranges::empty(expected); // Validate lack of size diff --git a/tests/std/tests/P0896R4_views_reverse/test.cpp b/tests/std/tests/P0896R4_views_reverse/test.cpp index be463bfd8f7..1ad9d61cac8 100644 --- a/tests/std/tests/P0896R4_views_reverse/test.cpp +++ b/tests/std/tests/P0896R4_views_reverse/test.cpp @@ -307,7 +307,7 @@ constexpr bool test_one(Rng&& rng, Expected&& expected) { struct instantiator { template static constexpr void call() { - R r{}; + R r{span{}}; test_one(r, span{}); } }; @@ -357,13 +357,6 @@ int main() { 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(); diff --git a/tests/std/tests/P0896R4_views_split/test.cpp b/tests/std/tests/P0896R4_views_split/test.cpp index 548cc07c6bf..b2fcf8c6c57 100644 --- a/tests/std/tests/P0896R4_views_split/test.cpp +++ b/tests/std/tests/P0896R4_views_split/test.cpp @@ -282,21 +282,21 @@ struct instantiator { Read read{span{text}}; test_one(move_if_needed(read), ' ', expected_single); - Read empty{}; + Read empty{span{}}; test_one(move_if_needed(empty), ' ', views::empty); } { // Empty delimiter Read read{span{text}}; test_one(move_if_needed(read), views::empty, expected_empty); - Read empty{}; + Read empty{span{}}; test_one(move_if_needed(empty), views::empty, views::empty); } if constexpr (ranges::forward_range) { // Range delimiter Read read{span{text}}; test_one(move_if_needed(read), "is"sv, expected_range); - Read empty{}; + Read empty{span{}}; test_one(move_if_needed(empty), "is"sv, views::empty); } } @@ -317,13 +317,15 @@ constexpr bool instantiation_test() { // 4. Commonality // 3. Length of delimiter pattern (0/static 1/dynamic) [covered in instantiator::call] - instantiator::call>(); - instantiator::call>(); - instantiator::call>(); + if (!std::is_constant_evaluated()) { // TRANSITION, P2231R1 + instantiator::call>(); + instantiator::call>(); + instantiator::call>(); - instantiator::call>(); - instantiator::call>(); - instantiator::call>(); + instantiator::call>(); + instantiator::call>(); + instantiator::call>(); + } instantiator::call>(); instantiator::call>(); diff --git a/tests/std/tests/P0896R4_views_take/test.cpp b/tests/std/tests/P0896R4_views_take/test.cpp index 13ddcd70d4c..8e0b42bc9d5 100644 --- a/tests/std/tests/P0896R4_views_take/test.cpp +++ b/tests/std/tests/P0896R4_views_take/test.cpp @@ -429,7 +429,7 @@ struct instantiator { R r{some_ints}; test_one(r, only_four_ints); - R empty_range{}; + R empty_range{span{}}; test_one(empty_range, span{}); } }; @@ -580,11 +580,6 @@ int main() { instantiation_test(); { - // Validate a non-view borrowed range - constexpr span s{some_ints}; - STATIC_ASSERT(test_one(s, only_four_ints)); - test_one(s, only_four_ints); - // Validate a view borrowed range constexpr auto v = views::iota(0ull, ranges::size(some_ints)) | views::transform([](auto i) { return some_ints[i]; }); diff --git a/tests/std/tests/P0896R4_views_take_while/test.cpp b/tests/std/tests/P0896R4_views_take_while/test.cpp index 2b3dbe1cd55..8c0133ab5d3 100644 --- a/tests/std/tests/P0896R4_views_take_while/test.cpp +++ b/tests/std/tests/P0896R4_views_take_while/test.cpp @@ -432,13 +432,6 @@ int main() { test_one(lst, expected_output); } - // Validate a non-view borrowed range - { - constexpr span s{some_ints}; - STATIC_ASSERT(test_one(s, expected_output)); - test_one(s, expected_output); - } - // take_while/reverse interaction test { auto twr_pipe = views::take_while(is_less_than<3>) | views::reverse; diff --git a/tests/std/tests/P0896R4_views_take_while_death/test.cpp b/tests/std/tests/P0896R4_views_take_while_death/test.cpp index 46832d246f7..3ebc5d93dd9 100644 --- a/tests/std/tests/P0896R4_views_take_while_death/test.cpp +++ b/tests/std/tests/P0896R4_views_take_while_death/test.cpp @@ -9,22 +9,43 @@ #include using namespace std; -[[maybe_unused]] constexpr auto lambda = [x = 42](int) { return x == 42; }; -using TWV = decltype(ranges::take_while_view{span{}, lambda}); +struct test_predicate { + struct tag {}; + + test_predicate() = default; + test_predicate(const test_predicate&) { + throw tag{}; + } + test_predicate& operator=(const test_predicate&) = delete; + + constexpr bool operator()(int i) const { + return i == 42; + } +}; + +auto with_no_predicate() { + using TWV = decltype(ranges::take_while_view{span{}, test_predicate{}}); + TWV r; + try { + r = TWV{}; + } catch (const test_predicate::tag&) { + } + return r; +} void test_view_predicate() { - TWV r; - (void) r.pred(); // value-initialized take_while_view has no predicate + auto r = with_no_predicate(); + (void) r.pred(); // take_while_view has no predicate } void test_view_end() { - TWV r; - (void) r.end(); // N4868 [range.take_while.view] forbids calling end on a take_while_view that holds no predicate + auto r = with_no_predicate(); + (void) r.end(); // cannot call end on a take_while_view with no predicate } void test_view_const_end() { - const TWV r; - (void) r.end(); // N4868 [range.take_while.view] forbids calling end on a take_while_view that holds no predicate + const auto r = with_no_predicate(); + (void) r.end(); // cannot call end on a take_while_view with no predicate } int main(int argc, char* argv[]) { diff --git a/tests/std/tests/P0896R4_views_transform/test.cpp b/tests/std/tests/P0896R4_views_transform/test.cpp index f31580d6e0a..ec8ee4e15ff 100644 --- a/tests/std/tests/P0896R4_views_transform/test.cpp +++ b/tests/std/tests/P0896R4_views_transform/test.cpp @@ -436,9 +436,12 @@ struct iterator_instantiator { input_iterator_tag>>); { // Validate iterator special member functions and base - I defaultConstructed{}; - assert(std::move(defaultConstructed).base().peek() == nullptr); - STATIC_ASSERT(is_nothrow_default_constructible_v); + STATIC_ASSERT(default_initializable == default_initializable); + if constexpr (default_initializable) { + I defaultConstructed{}; + assert(move(defaultConstructed).base().peek() == nullptr); + STATIC_ASSERT(is_nothrow_default_constructible_v); + } auto r0 = make_view(); I valueConstructed{r0, Iter{mutable_ints}}; @@ -449,11 +452,13 @@ struct iterator_instantiator { assert(copyConstructed == valueConstructed); STATIC_ASSERT(is_nothrow_copy_constructible_v); - defaultConstructed = copyConstructed; - assert(defaultConstructed == valueConstructed); + auto r1 = make_view(); + I copyAssigned{r1, Iter{mutable_ints + 8}}; + copyAssigned = copyConstructed; + assert(copyAssigned == valueConstructed); STATIC_ASSERT(is_nothrow_copy_assignable_v); } - assert(std::move(valueConstructed).base().peek() == mutable_ints); + assert(move(valueConstructed).base().peek() == mutable_ints); if constexpr (forward_iterator) { auto r1 = make_view(); @@ -518,7 +523,7 @@ struct iterator_instantiator { auto r0 = make_view(); auto i0 = r0.begin(); assert(&++i0 == &i0); - assert(std::move(i0).base().peek() == mutable_ints + 1); + assert(move(i0).base().peek() == mutable_ints + 1); STATIC_ASSERT(noexcept(++i0)); auto r1 = make_view(); @@ -528,7 +533,7 @@ struct iterator_instantiator { } else { i1++; } - assert(std::move(i1).base().peek() == mutable_ints + 1); + assert(move(i1).base().peek() == mutable_ints + 1); STATIC_ASSERT(noexcept(i0++)); } @@ -752,12 +757,6 @@ int main() { instantiation_test(); } - { // Validate a non-view borrowed range - constexpr span s{some_ints}; - STATIC_ASSERT(test_one(s, transformed_ints)); - test_one(s, transformed_ints); - } - STATIC_ASSERT((iterator_instantiation_test(), true)); iterator_instantiation_test(); diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp index 0da859a6bf9..cfc969b6c57 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.compile.pass.cpp @@ -1224,10 +1224,10 @@ STATIC_ASSERT(__cpp_lib_quoted_string_io == 201304L); #if _HAS_CXX23 && !defined(__EDG__) // TRANSITION, EDG concepts support and GH-1814 #ifndef __cpp_lib_ranges #error __cpp_lib_ranges is not defined -#elif __cpp_lib_ranges != 201911L -#error __cpp_lib_ranges is not 201911L +#elif __cpp_lib_ranges != 202106L +#error __cpp_lib_ranges is not 202106L #else -STATIC_ASSERT(__cpp_lib_ranges == 201911L); +STATIC_ASSERT(__cpp_lib_ranges == 202106L); #endif #else #ifdef __cpp_lib_ranges