diff --git a/stl/inc/vector b/stl/inc/vector index fe53326da9f..1d6143bff3d 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -37,13 +37,16 @@ public: using _Tptr = typename _Myvec::pointer; - _Vector_const_iterator() noexcept : _Ptr() {} + _CONSTEXPR20_CONTAINER _Vector_const_iterator() noexcept : _Ptr() {} - _Vector_const_iterator(_Tptr _Parg, const _Container_base* _Pvector) noexcept : _Ptr(_Parg) { + _CONSTEXPR20_CONTAINER _Vector_const_iterator(_Tptr _Parg, const _Container_base* _Pvector) noexcept : _Ptr(_Parg) { this->_Adopt(_Pvector); } - _NODISCARD reference operator*() const noexcept { + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator=(const _Vector_const_iterator&) noexcept = default; + + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); @@ -54,7 +57,7 @@ public: return *_Ptr; } - _NODISCARD pointer operator->() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER pointer operator->() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); @@ -65,7 +68,7 @@ public: return _Ptr; } - _Vector_const_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator++() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); @@ -76,13 +79,13 @@ public: return *this; } - _Vector_const_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator operator++(int) noexcept { _Vector_const_iterator _Tmp = *this; ++*this; return _Tmp; } - _Vector_const_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator--() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Mycont = static_cast(this->_Getcont()); _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); @@ -93,13 +96,13 @@ public: return *this; } - _Vector_const_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator operator--(int) noexcept { _Vector_const_iterator _Tmp = *this; --*this; return _Tmp; } - void _Verify_offset(const difference_type _Off) const noexcept { + _CONSTEXPR20_CONTAINER void _Verify_offset(const difference_type _Off) const noexcept { #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Off; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv @@ -115,62 +118,63 @@ public: #endif // _ITERATOR_DEBUG_LEVEL == 0 } - _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator+=(const difference_type _Off) noexcept { _Verify_offset(_Off); _Ptr += _Off; return *this; } - _NODISCARD _Vector_const_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_const_iterator operator+(const difference_type _Off) const noexcept { _Vector_const_iterator _Tmp = *this; return _Tmp += _Off; } - _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } - _NODISCARD _Vector_const_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_const_iterator operator-(const difference_type _Off) const noexcept { _Vector_const_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD difference_type operator-(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER difference_type operator-(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr - _Right._Ptr; } - _NODISCARD reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](const difference_type _Off) const noexcept { return *(*this + _Off); } - _NODISCARD bool operator==(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr == _Right._Ptr; } - _NODISCARD bool operator!=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const _Vector_const_iterator& _Right) const noexcept { return !(*this == _Right); } - _NODISCARD bool operator<(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const _Vector_const_iterator& _Right) const noexcept { _Compat(_Right); return _Ptr < _Right._Ptr; } - _NODISCARD bool operator>(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const _Vector_const_iterator& _Right) const noexcept { return _Right < *this; } - _NODISCARD bool operator<=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const _Vector_const_iterator& _Right) const noexcept { return !(_Right < *this); } - _NODISCARD bool operator>=(const _Vector_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const _Vector_const_iterator& _Right) const noexcept { return !(*this < _Right); } - void _Compat(const _Vector_const_iterator& _Right) const noexcept { // test for compatible iterator pair + _CONSTEXPR20_CONTAINER void _Compat(const _Vector_const_iterator& _Right) const noexcept { + // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 0 vvv @@ -179,7 +183,8 @@ public: } #if _ITERATOR_DEBUG_LEVEL != 0 - friend void _Verify_range(const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { + friend _CONSTEXPR20_CONTAINER void _Verify_range( + const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { _STL_VERIFY(_First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); } @@ -187,11 +192,11 @@ public: using _Prevent_inheriting_unwrap = _Vector_const_iterator; - _NODISCARD const value_type* _Unwrapped() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const value_type* _Unwrapped() const noexcept { return _Unfancy(_Ptr); } - void _Seek_to(const value_type* _It) noexcept { + _CONSTEXPR20_CONTAINER void _Seek_to(const value_type* _It) noexcept { _Ptr = _Refancy<_Tptr>(const_cast(_It)); } @@ -199,7 +204,7 @@ public: }; template -_NODISCARD _Vector_const_iterator<_Myvec> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vector_const_iterator<_Myvec> operator+( typename _Vector_const_iterator<_Myvec>::difference_type _Off, _Vector_const_iterator<_Myvec> _Next) noexcept { return _Next += _Off; } @@ -248,71 +253,81 @@ public: using _Mybase::_Mybase; - _NODISCARD reference operator*() const noexcept { + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vector_iterator& operator=(const _Vector_iterator&) noexcept = default; + + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { return const_cast(_Mybase::operator*()); } - _NODISCARD pointer operator->() const noexcept { - return _Const_cast(_Mybase::operator->()); + _NODISCARD _CONSTEXPR20_CONTAINER pointer operator->() const noexcept { +#if _ITERATOR_DEBUG_LEVEL != 0 + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(this->_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst <= this->_Ptr && this->_Ptr < _Mycont->_Mylast, + "can't dereference out of range vector iterator"); +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + return this->_Ptr; } - _Vector_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator++() noexcept { _Mybase::operator++(); return *this; } - _Vector_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator operator++(int) noexcept { _Vector_iterator _Tmp = *this; _Mybase::operator++(); return _Tmp; } - _Vector_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator--() noexcept { _Mybase::operator--(); return *this; } - _Vector_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator operator--(int) noexcept { _Vector_iterator _Tmp = *this; _Mybase::operator--(); return _Tmp; } - _Vector_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator+=(const difference_type _Off) noexcept { _Mybase::operator+=(_Off); return *this; } - _NODISCARD _Vector_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_iterator operator+(const difference_type _Off) const noexcept { _Vector_iterator _Tmp = *this; return _Tmp += _Off; } - _Vector_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vector_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; } using _Mybase::operator-; - _NODISCARD _Vector_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vector_iterator operator-(const difference_type _Off) const noexcept { _Vector_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](const difference_type _Off) const noexcept { return const_cast(_Mybase::operator[](_Off)); } using _Prevent_inheriting_unwrap = _Vector_iterator; - _NODISCARD value_type* _Unwrapped() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER value_type* _Unwrapped() const noexcept { return _Unfancy(this->_Ptr); } }; template -_NODISCARD _Vector_iterator<_Myvec> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vector_iterator<_Myvec> operator+( typename _Vector_iterator<_Myvec>::difference_type _Off, _Vector_iterator<_Myvec> _Next) noexcept { return _Next += _Off; } @@ -372,19 +387,19 @@ public: using reference = value_type&; using const_reference = const value_type&; - _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} + _CONSTEXPR20_CONTAINER _Vector_val() noexcept : _Myfirst(), _Mylast(), _Myend() {} - _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept + _CONSTEXPR20_CONTAINER _Vector_val(pointer _First, pointer _Last, pointer _End) noexcept : _Myfirst(_First), _Mylast(_Last), _Myend(_End) {} - void _Swap_val(_Vector_val& _Right) noexcept { + _CONSTEXPR20_CONTAINER void _Swap_val(_Vector_val& _Right) noexcept { this->_Swap_proxy_and_iterators(_Right); _Swap_adl(_Myfirst, _Right._Myfirst); _Swap_adl(_Mylast, _Right._Mylast); _Swap_adl(_Myend, _Right._Myend); } - void _Take_contents(_Vector_val& _Right) noexcept { + _CONSTEXPR20_CONTAINER void _Take_contents(_Vector_val& _Right) noexcept { this->_Swap_proxy_and_iterators(_Right); _Myfirst = _Right._Myfirst; _Mylast = _Right._Mylast; @@ -402,12 +417,13 @@ public: // FUNCTION TEMPLATE _Unfancy_maybe_null template -auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { // converts from a (potentially null) fancy pointer to a plain pointer +constexpr auto _Unfancy_maybe_null(_Ptrty _Ptr) noexcept { + // converts from a (potentially null) fancy pointer to a plain pointer return _Ptr ? _STD addressof(*_Ptr) : nullptr; } template -_Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers +constexpr _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers return _Ptr; } @@ -445,17 +461,18 @@ public: using reverse_iterator = _STD reverse_iterator; using const_reverse_iterator = _STD reverse_iterator; - vector() noexcept(is_nothrow_default_constructible_v<_Alty>) : _Mypair(_Zero_then_variadic_args_t{}) { + _CONSTEXPR20_CONTAINER vector() noexcept(is_nothrow_default_constructible_v<_Alty>) + : _Mypair(_Zero_then_variadic_args_t{}) { _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); } - explicit vector(const _Alloc& _Al) noexcept : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER explicit vector(const _Alloc& _Al) noexcept : _Mypair(_One_then_variadic_args_t{}, _Al) { _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); } private: template - void _Construct_n_copies_of_ty(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty2& _Val) { + _CONSTEXPR20_CONTAINER void _Construct_n_copies_of_ty(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty2& _Val) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); auto& _My_data = _Mypair._Myval2; _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); @@ -470,19 +487,20 @@ private: } public: - explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) + _CONSTEXPR20_CONTAINER explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Construct_n_copies_of_ty(_Count, _Value_init_tag{}); } - vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) + _CONSTEXPR20_CONTAINER vector( + _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { _Construct_n_copies_of_ty(_Count, _Val); } private: template - void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) { _Tidy_guard _Guard{this}; for (; _First != _Last; ++_First) { emplace_back(*_First); // performance note: emplace_back()'s strong guarantee is unnecessary here @@ -492,7 +510,7 @@ private: } template - void _Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag) { const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); if (_Count != 0) { _Buy_nonzero(_Count); @@ -505,7 +523,8 @@ private: public: template , int> = 0> - vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); _Adl_verify_range(_First, _Last); @@ -513,14 +532,15 @@ public: _Proxy._Release(); } - vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) + : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); _Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); _Proxy._Release(); } - vector(const vector& _Right) + _CONSTEXPR20_CONTAINER vector(const vector& _Right) : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); auto& _My_data = _Mypair._Myval2; @@ -538,7 +558,7 @@ public: _Proxy._Release(); } - vector(const vector& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { + _CONSTEXPR20_CONTAINER vector(const vector& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); auto& _My_data = _Mypair._Myval2; const auto& _Right_data = _Right._Mypair._Myval2; @@ -556,11 +576,13 @@ public: } private: - void _Move_construct(vector& _Right, true_type) noexcept { // move from _Right, stealing its contents + _CONSTEXPR20_CONTAINER void _Move_construct(vector& _Right, true_type) noexcept { + // move from _Right, stealing its contents _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); } - void _Move_construct(vector& _Right, false_type) { // move from _Right, possibly moving its contents + _CONSTEXPR20_CONTAINER void _Move_construct(vector& _Right, false_type) { + // move from _Right, possibly moving its contents if constexpr (!_Alty_traits::is_always_equal::value) { if (_Getal() != _Right._Getal()) { const auto& _Right_data = _Right._Mypair._Myval2; @@ -581,7 +603,7 @@ private: } public: - vector(vector&& _Right) noexcept + _CONSTEXPR20_CONTAINER vector(vector&& _Right) noexcept : _Mypair(_One_then_variadic_args_t{}, _STD move(_Right._Getal()), _STD exchange(_Right._Mypair._Myval2._Myfirst, nullptr), _STD exchange(_Right._Mypair._Myval2._Mylast, nullptr), @@ -590,7 +612,8 @@ public: _Mypair._Myval2._Swap_proxy_and_iterators(_Right._Mypair._Myval2); } - vector(vector&& _Right, const _Alloc& _Al) noexcept(_Alty_traits::is_always_equal::value) // strengthened + _CONSTEXPR20_CONTAINER vector(vector&& _Right, const _Alloc& _Al) noexcept( + _Alty_traits::is_always_equal::value) // strengthened : _Mypair(_One_then_variadic_args_t{}, _Al) { auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); @@ -599,13 +622,13 @@ public: } private: - void _Move_assign(vector& _Right, _Equal_allocators) noexcept { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Equal_allocators) noexcept { _Tidy(); _Pocma(_Getal(), _Right._Getal()); _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); } - void _Move_assign(vector& _Right, _Propagate_allocators) noexcept /* terminates */ { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Propagate_allocators) noexcept /* terminates */ { _Tidy(); #if _ITERATOR_DEBUG_LEVEL != 0 if (_Getal() != _Right._Getal()) { @@ -619,7 +642,7 @@ private: _Mypair._Myval2._Take_contents(_Right._Mypair._Myval2); } - void _Move_assign(vector& _Right, _No_propagate_allocators) { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _No_propagate_allocators) { if (_Getal() == _Right._Getal()) { _Move_assign(_Right, _Equal_allocators{}); } else { @@ -665,7 +688,8 @@ private: } public: - vector& operator=(vector&& _Right) noexcept(noexcept(_Move_assign(_Right, _Choose_pocma<_Alty>{}))) { + _CONSTEXPR20_CONTAINER vector& operator=(vector&& _Right) noexcept( + noexcept(_Move_assign(_Right, _Choose_pocma<_Alty>{}))) { if (this != _STD addressof(_Right)) { _Move_assign(_Right, _Choose_pocma<_Alty>{}); } @@ -673,7 +697,7 @@ public: return *this; } - ~vector() noexcept { + _CONSTEXPR20_CONTAINER ~vector() noexcept { _Tidy(); #if _ITERATOR_DEBUG_LEVEL != 0 auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); @@ -683,7 +707,7 @@ public: private: template - decltype(auto) _Emplace_back_with_unused_capacity(_Valty&&... _Val) { + _CONSTEXPR20_CONTAINER decltype(auto) _Emplace_back_with_unused_capacity(_Valty&&... _Val) { // insert by perfectly forwarding into element at end, provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; @@ -701,7 +725,7 @@ private: public: template - decltype(auto) emplace_back(_Valty&&... _Val) { + _CONSTEXPR20_CONTAINER decltype(auto) emplace_back(_Valty&&... _Val) { // insert by perfectly forwarding into element at end, provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; @@ -717,16 +741,17 @@ public: #endif // _HAS_CXX17 } - void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee + _CONSTEXPR20_CONTAINER void push_back(const _Ty& _Val) { // insert element at end, provide strong guarantee emplace_back(_Val); } - void push_back(_Ty&& _Val) { // insert by moving into element at end, provide strong guarantee + _CONSTEXPR20_CONTAINER void push_back(_Ty&& _Val) { + // insert by moving into element at end, provide strong guarantee emplace_back(_STD move(_Val)); } template - pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) { + _CONSTEXPR20_CONTAINER pointer _Emplace_reallocate(const pointer _Whereptr, _Valty&&... _Val) { // reallocate and insert by perfectly forwarding _Val at _Whereptr _Alty& _Al = _Getal(); auto& _My_data = _Mypair._Myval2; @@ -771,7 +796,8 @@ public: } template - iterator emplace(const_iterator _Where, _Valty&&... _Val) { // insert by perfectly forwarding _Val at _Where + _CONSTEXPR20_CONTAINER iterator emplace(const_iterator _Where, _Valty&&... _Val) { + // insert by perfectly forwarding _Val at _Where const pointer _Whereptr = _Where._Ptr; auto& _My_data = _Mypair._Myval2; const pointer _Oldlast = _My_data._Mylast; @@ -801,15 +827,16 @@ public: return _Make_iterator(_Emplace_reallocate(_Whereptr, _STD forward<_Valty>(_Val)...)); } - iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, const _Ty& _Val) { // insert _Val at _Where return emplace(_Where, _Val); } - iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, _Ty&& _Val) { // insert by moving _Val at _Where return emplace(_Where, _STD move(_Val)); } - iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val) { + _CONSTEXPR20_CONTAINER iterator insert( + const_iterator _Where, _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val) { // insert _Count * _Val at _Where const pointer _Whereptr = _Where._Ptr; @@ -883,7 +910,7 @@ public: private: template - void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { // insert input range [_First, _Last) at _Where if (_First == _Last) { return; // nothing to do, avoid invalidating iterators @@ -909,7 +936,7 @@ private: } template - void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert_range(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { // insert forward range [_First, _Last) at _Where const pointer _Whereptr = _Where._Ptr; const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); @@ -1018,7 +1045,7 @@ private: public: template , int> = 0> - iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { const pointer _Whereptr = _Where._Ptr; auto& _My_data = _Mypair._Myval2; const pointer _Oldfirst = _My_data._Myfirst; @@ -1034,11 +1061,12 @@ public: return _Make_iterator_offset(_Whereoff); } - iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, initializer_list<_Ty> _Ilist) { return insert(_Where, _Ilist.begin(), _Ilist.end()); } - void assign(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { // assign _Newsize * _Val + _CONSTEXPR20_CONTAINER void assign(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { + // assign _Newsize * _Val auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1066,7 +1094,8 @@ public: private: template - void _Assign_range(_Iter _First, _Iter _Last, input_iterator_tag) { // assign input range [_First, _Last) + _CONSTEXPR20_CONTAINER void _Assign_range(_Iter _First, _Iter _Last, input_iterator_tag) { + // assign input range [_First, _Last) auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1095,7 +1124,8 @@ private: } template - void _Assign_range(_Iter _First, _Iter _Last, forward_iterator_tag) { // assign forward range [_First, _Last) + _CONSTEXPR20_CONTAINER void _Assign_range(_Iter _First, _Iter _Last, forward_iterator_tag) { + // assign forward range [_First, _Last) const auto _Newsize = _Convert_size(static_cast(_STD distance(_First, _Last))); auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1107,54 +1137,59 @@ private: if constexpr (conjunction_v::_Trivially_copyable>, _Uses_default_construct<_Alty, _Ty*, decltype(*_First)>, _Uses_default_destroy<_Alty, _Ty*>>) { - const auto _Oldcapacity = static_cast(_Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { - _Clear_and_reserve_geometric(_Newsize); - } - - _Mylast = _Refancy(_Copy_memmove(_First, _Last, _Unfancy(_Myfirst))); - } else { - auto _Oldsize = static_cast(_Mylast - _Myfirst); - - if (_Newsize > _Oldsize) { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_constexpr_dynamic_alloc + { const auto _Oldcapacity = static_cast(_Myend - _Myfirst); - if (_Newsize > _Oldcapacity) { // reallocate + if (_Newsize > _Oldcapacity) { _Clear_and_reserve_geometric(_Newsize); - _Oldsize = 0; } - // performance note: traversing [_First, _Mid) twice - const _Iter _Mid = _STD next(_First, static_cast(_Oldsize)); - _Copy_unchecked(_First, _Mid, _Myfirst); - _Mylast = _Ucopy(_Mid, _Last, _Mylast); - } else { - const pointer _Newlast = _Myfirst + _Newsize; - _Copy_unchecked(_First, _Last, _Myfirst); - _Destroy(_Newlast, _Mylast); - _Mylast = _Newlast; + _Mylast = _Refancy(_Copy_memmove(_First, _Last, _Unfancy(_Myfirst))); + return; } } + auto _Oldsize = static_cast(_Mylast - _Myfirst); + + if (_Newsize > _Oldsize) { + const auto _Oldcapacity = static_cast(_Myend - _Myfirst); + if (_Newsize > _Oldcapacity) { // reallocate + _Clear_and_reserve_geometric(_Newsize); + _Oldsize = 0; + } + + // performance note: traversing [_First, _Mid) twice + const _Iter _Mid = _STD next(_First, static_cast(_Oldsize)); + _Copy_unchecked(_First, _Mid, _Myfirst); + _Mylast = _Ucopy(_Mid, _Last, _Mylast); + } else { + const pointer _Newlast = _Myfirst + _Newsize; + _Copy_unchecked(_First, _Last, _Myfirst); + _Destroy(_Newlast, _Mylast); + _Mylast = _Newlast; + } } public: template , int> = 0> - void assign(_Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER void assign(_Iter _First, _Iter _Last) { _Adl_verify_range(_First, _Last); _Assign_range(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Iter_cat_t<_Iter>{}); } - void assign(initializer_list<_Ty> _Ilist) { + _CONSTEXPR20_CONTAINER void assign(initializer_list<_Ty> _Ilist) { _Assign_range(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); } private: - void _Copy_assign(const vector& _Right, false_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, false_type) { _Pocca(_Getal(), _Right._Getal()); auto& _Right_data = _Right._Mypair._Myval2; assign(_Right_data._Myfirst, _Right_data._Mylast); } - void _Copy_assign(const vector& _Right, true_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, true_type) { if (_Getal() != _Right._Getal()) { _Tidy(); _Mypair._Myval2._Reload_proxy( @@ -1165,7 +1200,7 @@ private: } public: - vector& operator=(const vector& _Right) { + _CONSTEXPR20_CONTAINER vector& operator=(const vector& _Right) { if (this != _STD addressof(_Right)) { _Copy_assign(_Right, _Choose_pocca<_Alty>{}); } @@ -1173,14 +1208,14 @@ public: return *this; } - vector& operator=(initializer_list<_Ty> _Ilist) { + _CONSTEXPR20_CONTAINER vector& operator=(initializer_list<_Ty> _Ilist) { _Assign_range(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); return *this; } private: template - void _Resize_reallocate(const size_type _Newsize, const _Ty2& _Val) { + _CONSTEXPR20_CONTAINER void _Resize_reallocate(const size_type _Newsize, const _Ty2& _Val) { if (_Newsize > max_size()) { _Xlength(); } @@ -1209,7 +1244,8 @@ private: } template - void _Resize(const size_type _Newsize, const _Ty2& _Val) { // trim or append elements, provide strong guarantee + _CONSTEXPR20_CONTAINER void _Resize(const size_type _Newsize, const _Ty2& _Val) { + // trim or append elements, provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1238,18 +1274,18 @@ private: } public: - void resize(_CRT_GUARDOVERFLOW const size_type _Newsize) { + _CONSTEXPR20_CONTAINER void resize(_CRT_GUARDOVERFLOW const size_type _Newsize) { // trim or append value-initialized elements, provide strong guarantee _Resize(_Newsize, _Value_init_tag{}); } - void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { + _CONSTEXPR20_CONTAINER void resize(_CRT_GUARDOVERFLOW const size_type _Newsize, const _Ty& _Val) { // trim or append copies of _Val, provide strong guarantee _Resize(_Newsize, _Val); } private: - void _Reallocate_exactly(const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Reallocate_exactly(const size_type _Newcapacity) { // set capacity to _Newcapacity (without geometric growth), provide strong guarantee auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1269,7 +1305,27 @@ private: _Change_array(_Newvec, _Size, _Newcapacity); } - void _Clear_and_reserve_geometric(const size_type _Newsize) { +#if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) + void _Check_all_orphaned_locked() const noexcept { + _Lockit _Lock(_LOCK_DEBUG); + auto& _My_data = _Mypair._Myval2; + _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); + } + + _CONSTEXPR20_CONTAINER void _Check_all_orphaned() const noexcept { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + auto& _My_data = _Mypair._Myval2; + _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Check_all_orphaned_locked(); + } + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) + + _CONSTEXPR20_CONTAINER void _Clear_and_reserve_geometric(const size_type _Newsize) { auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1277,10 +1333,7 @@ private: #if _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) _STL_INTERNAL_CHECK(_Newsize != 0); - { - _Lockit _Lock(_LOCK_DEBUG); - _STL_INTERNAL_CHECK(!_My_data._Myproxy->_Myfirstiter); // asserts that all iterators are orphaned - } // unlock + _Check_all_orphaned(); #endif // _ITERATOR_DEBUG_LEVEL != 0 && defined(_ENABLE_STL_INTERNAL_CHECK) if (_Newsize > max_size()) { @@ -1302,7 +1355,7 @@ private: } public: - void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void reserve(_CRT_GUARDOVERFLOW const size_type _Newcapacity) { // increase capacity to _Newcapacity (without geometric growth), provide strong guarantee if (_Newcapacity > capacity()) { // something to do (reserve() never shrinks) if (_Newcapacity > max_size()) { @@ -1313,7 +1366,7 @@ public: } } - void shrink_to_fit() { // reduce capacity to size, provide strong guarantee + _CONSTEXPR20_CONTAINER void shrink_to_fit() { // reduce capacity to size, provide strong guarantee auto& _My_data = _Mypair._Myval2; const pointer _Oldlast = _My_data._Mylast; if (_Oldlast != _My_data._Myend) { // something to do @@ -1326,20 +1379,21 @@ public: } } - void pop_back() noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void pop_back() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); - _Orphan_range(_Mylast - 1, _Mylast); #endif // _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(_Mylast - 1, _Mylast); _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); --_Mylast; } - iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v) /* strengthened */ { + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _Where) noexcept( + is_nothrow_move_assignable_v) /* strengthened */ { const pointer _Whereptr = _Where._Ptr; auto& _My_data = _Mypair._Myval2; pointer& _Mylast = _My_data._Mylast; @@ -1348,16 +1402,16 @@ public: _STL_VERIFY( _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, "vector erase iterator outside range"); - _Orphan_range(_Whereptr, _Mylast); #endif // _ITERATOR_DEBUG_LEVEL == 2 + _Orphan_range(_Whereptr, _Mylast); _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr); _Alty_traits::destroy(_Getal(), _Unfancy(_Mylast - 1)); --_Mylast; return iterator(_Whereptr, _STD addressof(_My_data)); } - iterator erase(const_iterator _First, const_iterator _Last) noexcept( + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _First, const_iterator _Last) noexcept( is_nothrow_move_assignable_v) /* strengthened */ { const pointer _Firstptr = _First._Ptr; const pointer _Lastptr = _Last._Ptr; @@ -1381,7 +1435,7 @@ public: return iterator(_Firstptr, _STD addressof(_My_data)); } - void clear() noexcept { // erase all + _CONSTEXPR20_CONTAINER void clear() noexcept { // erase all auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1391,111 +1445,110 @@ public: _Mylast = _Myfirst; } -public: - void swap(vector& _Right) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void swap(vector& _Right) noexcept /* strengthened */ { if (this != _STD addressof(_Right)) { _Pocs(_Getal(), _Right._Getal()); _Mypair._Myval2._Swap_val(_Right._Mypair._Myval2); } } - _NODISCARD _Ty* data() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty* data() noexcept { return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); } - _NODISCARD const _Ty* data() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty* data() const noexcept { return _Unfancy_maybe_null(_Mypair._Myval2._Myfirst); } - _NODISCARD iterator begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator begin() noexcept { auto& _My_data = _Mypair._Myval2; return iterator(_My_data._Myfirst, _STD addressof(_My_data)); } - _NODISCARD const_iterator begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator begin() const noexcept { auto& _My_data = _Mypair._Myval2; return const_iterator(_My_data._Myfirst, _STD addressof(_My_data)); } - _NODISCARD iterator end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator end() noexcept { auto& _My_data = _Mypair._Myval2; return iterator(_My_data._Mylast, _STD addressof(_My_data)); } - _NODISCARD const_iterator end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator end() const noexcept { auto& _My_data = _Mypair._Myval2; return const_iterator(_My_data._Mylast, _STD addressof(_My_data)); } - _NODISCARD reverse_iterator rbegin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _NODISCARD const_reverse_iterator rbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _NODISCARD reverse_iterator rend() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _NODISCARD const_reverse_iterator rend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - _NODISCARD const_iterator cbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cbegin() const noexcept { return begin(); } - _NODISCARD const_iterator cend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cend() const noexcept { return end(); } - _NODISCARD const_reverse_iterator crbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crbegin() const noexcept { return rbegin(); } - _NODISCARD const_reverse_iterator crend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crend() const noexcept { return rend(); } - pointer _Unchecked_begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER pointer _Unchecked_begin() noexcept { return _Mypair._Myval2._Myfirst; } - const_pointer _Unchecked_begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_pointer _Unchecked_begin() const noexcept { return _Mypair._Myval2._Myfirst; } - pointer _Unchecked_end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER pointer _Unchecked_end() noexcept { return _Mypair._Myval2._Mylast; } - const_pointer _Unchecked_end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_pointer _Unchecked_end() const noexcept { return _Mypair._Myval2._Mylast; } - _NODISCARD bool empty() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool empty() const noexcept { auto& _My_data = _Mypair._Myval2; return _My_data._Myfirst == _My_data._Mylast; } - _NODISCARD size_type size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type size() const noexcept { auto& _My_data = _Mypair._Myval2; return static_cast(_My_data._Mylast - _My_data._Myfirst); } - _NODISCARD size_type max_size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type max_size() const noexcept { return (_STD min)( static_cast((numeric_limits::max)()), _Alty_traits::max_size(_Getal())); } - _NODISCARD size_type capacity() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type capacity() const noexcept { auto& _My_data = _Mypair._Myval2; return static_cast(_My_data._Myend - _My_data._Myfirst); } - _NODISCARD _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& operator[](const size_type _Pos) noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( @@ -1505,7 +1558,7 @@ public: return _My_data._Myfirst[_Pos]; } - _NODISCARD const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& operator[](const size_type _Pos) const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY( @@ -1515,7 +1568,7 @@ public: return _My_data._Myfirst[_Pos]; } - _NODISCARD _Ty& at(const size_type _Pos) { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& at(const size_type _Pos) { auto& _My_data = _Mypair._Myval2; if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { _Xrange(); @@ -1524,7 +1577,7 @@ public: return _My_data._Myfirst[_Pos]; } - _NODISCARD const _Ty& at(const size_type _Pos) const { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& at(const size_type _Pos) const { auto& _My_data = _Mypair._Myval2; if (static_cast(_My_data._Mylast - _My_data._Myfirst) <= _Pos) { _Xrange(); @@ -1533,7 +1586,7 @@ public: return _My_data._Myfirst[_Pos]; } - _NODISCARD _Ty& front() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& front() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); @@ -1542,7 +1595,7 @@ public: return *_My_data._Myfirst; } - _NODISCARD const _Ty& front() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& front() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); @@ -1551,7 +1604,7 @@ public: return *_My_data._Myfirst; } - _NODISCARD _Ty& back() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER _Ty& back() noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); @@ -1560,7 +1613,7 @@ public: return _My_data._Mylast[-1]; } - _NODISCARD const _Ty& back() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const _Ty& back() const noexcept /* strengthened */ { auto& _My_data = _Mypair._Myval2; #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); @@ -1569,51 +1622,54 @@ public: return _My_data._Mylast[-1]; } - _NODISCARD allocator_type get_allocator() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER allocator_type get_allocator() const noexcept { return static_cast(_Getal()); } private: - pointer _Ufill(pointer _Dest, const size_type _Count, const _Ty& _Val) { + _CONSTEXPR20_CONTAINER pointer _Ufill(pointer _Dest, const size_type _Count, const _Ty& _Val) { // fill raw _Dest with _Count copies of _Val, using allocator return _Uninitialized_fill_n(_Dest, _Count, _Val, _Getal()); } - pointer _Ufill(pointer _Dest, const size_type _Count, _Value_init_tag) { + _CONSTEXPR20_CONTAINER pointer _Ufill(pointer _Dest, const size_type _Count, _Value_init_tag) { // fill raw _Dest with _Count value-initialized objects, using allocator return _Uninitialized_value_construct_n(_Dest, _Count, _Getal()); } template - pointer _Ucopy(_Iter _First, _Iter _Last, pointer _Dest) { // copy [_First, _Last) to raw _Dest, using allocator + _CONSTEXPR20_CONTAINER pointer _Ucopy(_Iter _First, _Iter _Last, pointer _Dest) { + // copy [_First, _Last) to raw _Dest, using allocator return _Uninitialized_copy(_First, _Last, _Dest, _Getal()); } - pointer _Umove(pointer _First, pointer _Last, pointer _Dest) { // move [_First, _Last) to raw _Dest, using allocator + _CONSTEXPR20_CONTAINER pointer _Umove(pointer _First, pointer _Last, pointer _Dest) { + // move [_First, _Last) to raw _Dest, using allocator return _Uninitialized_move(_First, _Last, _Dest, _Getal()); } - void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, true_type) { + _CONSTEXPR20_CONTAINER void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, true_type) { // move [_First, _Last) to raw _Dest, using allocator _Uninitialized_move(_First, _Last, _Dest, _Getal()); } - void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, false_type) { + _CONSTEXPR20_CONTAINER void _Umove_if_noexcept1(pointer _First, pointer _Last, pointer _Dest, false_type) { // copy [_First, _Last) to raw _Dest, using allocator _Uninitialized_copy(_First, _Last, _Dest, _Getal()); } - void _Umove_if_noexcept(pointer _First, pointer _Last, pointer _Dest) { + _CONSTEXPR20_CONTAINER void _Umove_if_noexcept(pointer _First, pointer _Last, pointer _Dest) { // move_if_noexcept [_First, _Last) to raw _Dest, using allocator _Umove_if_noexcept1(_First, _Last, _Dest, bool_constant, negation>>>{}); } - void _Destroy(pointer _First, pointer _Last) { // destroy [_First, _Last) using allocator + _CONSTEXPR20_CONTAINER void _Destroy(pointer _First, pointer _Last) { + // destroy [_First, _Last) using allocator _Destroy_range(_First, _Last, _Getal()); } - size_type _Calculate_growth(const size_type _Newsize) const { + _CONSTEXPR20_CONTAINER size_type _Calculate_growth(const size_type _Newsize) const { // given _Oldcapacity and _Newsize, calculate geometric growth const size_type _Oldcapacity = capacity(); const auto _Max = max_size(); @@ -1631,7 +1687,7 @@ private: return _Geometric; // geometric growth is sufficient } - void _Buy_raw(const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Buy_raw(const size_type _Newcapacity) { // allocate array with _Newcapacity elements auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1647,7 +1703,7 @@ private: _Myend = _Newvec + _Newcapacity; } - void _Buy_nonzero(const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Buy_nonzero(const size_type _Newcapacity) { // allocate array with _Newcapacity elements #ifdef _ENABLE_STL_INTERNAL_CHECK auto& _My_data = _Mypair._Myval2; @@ -1665,7 +1721,8 @@ private: _Buy_raw(_Newcapacity); } - void _Change_array(const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) { + _CONSTEXPR20_CONTAINER void _Change_array( + const pointer _Newvec, const size_type _Newsize, const size_type _Newcapacity) { // orphan all iterators, discard old array, acquire new array auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; @@ -1684,7 +1741,7 @@ private: _Myend = _Newvec + _Newcapacity; } - void _Tidy() noexcept { // free all storage + _CONSTEXPR20_CONTAINER void _Tidy() noexcept { // free all storage auto& _My_data = _Mypair._Myval2; pointer& _Myfirst = _My_data._Myfirst; pointer& _Mylast = _My_data._Mylast; @@ -1710,39 +1767,54 @@ private: _Xout_of_range("invalid vector subscript"); } - void _Orphan_range(pointer _First, pointer _Last) const { // orphan iterators within specified (inclusive) range #if _ITERATOR_DEBUG_LEVEL == 2 - _Lockit _Lock(_LOCK_DEBUG); - + _CONSTEXPR20_CONTAINER void _Orphan_range_unlocked(pointer _First, pointer _Last) const { _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter; while (*_Pnext) { const auto _Pnextptr = static_cast(**_Pnext)._Ptr; if (_Pnextptr < _First || _Last < _Pnextptr) { // skip the iterator - _Pnext = &(*_Pnext)->_Mynextiter; + const auto _Temp = *_Pnext; // TRANSITION, VSO-1269037 + _Pnext = &_Temp->_Mynextiter; } else { // orphan the iterator (*_Pnext)->_Myproxy = nullptr; *_Pnext = (*_Pnext)->_Mynextiter; } } -#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 2 vvv - (void) _First; - (void) _Last; -#endif // _ITERATOR_DEBUG_LEVEL == 2 } - _Alty& _Getal() noexcept { + void _Orphan_range_locked(pointer _First, pointer _Last) const { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_range_unlocked(_First, _Last); + } + + _CONSTEXPR20_CONTAINER void _Orphan_range(pointer _First, pointer _Last) const { + // orphan iterators within specified (inclusive) range +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _Orphan_range_unlocked(_First, _Last); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Orphan_range_locked(_First, _Last); + } + } +#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 ^^^ // vvv _ITERATOR_DEBUG_LEVEL != 2 vvv + _CONSTEXPR20_CONTAINER void _Orphan_range(pointer, pointer) const {} +#endif // _ITERATOR_DEBUG_LEVEL != 2 + + _NODISCARD _CONSTEXPR20_CONTAINER _Alty& _Getal() noexcept { return _Mypair._Get_first(); } - const _Alty& _Getal() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const _Alty& _Getal() const noexcept { return _Mypair._Get_first(); } - iterator _Make_iterator(const pointer _Ptr) noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Make_iterator(const pointer _Ptr) noexcept { return iterator(_Ptr, _STD addressof(_Mypair._Myval2)); } - iterator _Make_iterator_offset(const size_type _Offset) noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Make_iterator_offset(const size_type _Offset) noexcept { // return the iterator begin() + _Offset without a debugging check auto& _My_data = _Mypair._Myval2; return iterator(_My_data._Myfirst + _Offset, _STD addressof(_My_data)); @@ -1758,39 +1830,39 @@ vector(_Iter, _Iter, _Alloc = _Alloc()) -> vector<_Iter_value_t<_Iter>, _Alloc>; #endif // _HAS_CXX17 template -void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { +_CONSTEXPR20_CONTAINER void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right) noexcept /* strengthened */ { _Left.swap(_Right); } template -_NODISCARD bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return _Left.size() == _Right.size() && _STD equal(_Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin()); } template -_NODISCARD bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left == _Right); } template -_NODISCARD bool operator<(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return _STD lexicographical_compare( _Left._Unchecked_begin(), _Left._Unchecked_end(), _Right._Unchecked_begin(), _Right._Unchecked_end()); } template -_NODISCARD bool operator>(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return _Right < _Left; } template -_NODISCARD bool operator<=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Right < _Left); } template -_NODISCARD bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const vector<_Ty, _Alloc>& _Left, const vector<_Ty, _Alloc>& _Right) { return !(_Left < _Right); } @@ -1813,21 +1885,24 @@ public: using _Difference_type = typename allocator_traits<_Alvbase>::difference_type; using _Mycont = vector>; - _Vb_iter_base() = default; + _CONSTEXPR20_CONTAINER _Vb_iter_base() = default; - _Vb_iter_base(const _Vbase* _Ptr, _Size_type _Off, const _Container_base* _Mypvbool) noexcept + _CONSTEXPR20_CONTAINER _Vb_iter_base(const _Vbase* _Ptr, _Size_type _Off, const _Container_base* _Mypvbool) noexcept : _Myptr(_Ptr), _Myoff(_Off) { this->_Adopt(_Mypvbool); } - void _Advance(_Size_type _Off) noexcept { + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vb_iter_base& operator=(const _Vb_iter_base&) noexcept = default; + + _CONSTEXPR20_CONTAINER void _Advance(_Size_type _Off) noexcept { _Myoff += _Off; _Myptr += _Myoff / _VBITS; _Myoff %= _VBITS; } #if _ITERATOR_DEBUG_LEVEL != 0 - _Difference_type _Total_off(const _Mycont* _Cont) const noexcept { + _CONSTEXPR20_CONTAINER _Difference_type _Total_off(const _Mycont* _Cont) const noexcept { return static_cast<_Difference_type>(_VBITS * (_Myptr - _Cont->_Myvec.data()) + _Myoff); } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -1845,18 +1920,19 @@ class _Vb_reference : public _Vb_iter_base<_Alvbase_wrapped> { using _Difference_type = typename _Mybase::_Difference_type; // TRANSITION, ABI: non-trivial constructor - _Vb_reference() = default; + _CONSTEXPR20_CONTAINER _Vb_reference() = default; public: - _Vb_reference(const _Vb_reference&) = default; + _CONSTEXPR20_CONTAINER _Vb_reference(const _Vb_reference&) = default; - _Vb_reference(const _Mybase& _Right) noexcept : _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {} + _CONSTEXPR20_CONTAINER _Vb_reference(const _Mybase& _Right) noexcept + : _Mybase(_Right._Myptr, _Right._Myoff, _Right._Getcont()) {} - _Vb_reference& operator=(const _Vb_reference& _Right) noexcept { + _CONSTEXPR20_CONTAINER _Vb_reference& operator=(const _Vb_reference& _Right) noexcept { return *this = static_cast(_Right); } - _Vb_reference& operator=(bool _Val) noexcept { + _CONSTEXPR20_CONTAINER _Vb_reference& operator=(bool _Val) noexcept { if (_Val) { *const_cast<_Vbase*>(_Getptr()) |= _Mask(); } else { @@ -1866,15 +1942,15 @@ public: return *this; } - void flip() noexcept { + _CONSTEXPR20_CONTAINER void flip() noexcept { *const_cast<_Vbase*>(_Getptr()) ^= _Mask(); } - operator bool() const noexcept { + _CONSTEXPR20_CONTAINER operator bool() const noexcept { return (*_Getptr() & _Mask()) != 0; } - const _Vbase* _Getptr() const noexcept { + _CONSTEXPR20_CONTAINER const _Vbase* _Getptr() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Cont = static_cast(this->_Getcont()); _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); @@ -1885,14 +1961,14 @@ public: return this->_Myptr; } - friend void swap(_Vb_reference _Left, _Vb_reference _Right) noexcept { + friend _CONSTEXPR20_CONTAINER void swap(_Vb_reference _Left, _Vb_reference _Right) noexcept { bool _Val = _Left; // NOT _STD swap _Left = _Right; _Right = _Val; } protected: - _Vbase _Mask() const noexcept { + _CONSTEXPR20_CONTAINER _Vbase _Mask() const noexcept { return static_cast<_Vbase>(1) << this->_Myoff; } }; @@ -1916,11 +1992,15 @@ public: using pointer = const_reference*; using reference = const_reference; - _Vb_const_iterator() = default; + _CONSTEXPR20_CONTAINER _Vb_const_iterator() = default; + + _CONSTEXPR20_CONTAINER _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept + : _Mybase(_Ptr, 0, _Mypvbool) {} - _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept : _Mybase(_Ptr, 0, _Mypvbool) {} + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator=(const _Vb_const_iterator&) noexcept = default; - _NODISCARD const_reference operator*() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Cont = static_cast(this->_Getcont()); _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); @@ -1931,29 +2011,29 @@ public: return _Reft(*this); } - _Vb_const_iterator& operator++() noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator++() noexcept { _Inc(); return *this; } - _Vb_const_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator operator++(int) noexcept { _Vb_const_iterator _Tmp = *this; _Inc(); return _Tmp; } - _Vb_const_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator--() noexcept { _Dec(); return *this; } - _Vb_const_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator operator--(int) noexcept { _Vb_const_iterator _Tmp = *this; _Dec(); return _Tmp; } - _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator+=(const difference_type _Off) noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 if (_Off != 0) { const auto _Cont = static_cast(this->_Getcont()); @@ -1969,68 +2049,69 @@ public: #endif // _ITERATOR_DEBUG_LEVEL != 0 if (_Off < 0 && this->_Myoff < 0 - static_cast<_Size_type>(_Off)) { // add negative increment - this->_Myoff += _Off; + this->_Myoff += static_cast<_Size_type>(_Off); this->_Myptr -= 1 + (static_cast<_Size_type>(-1) - this->_Myoff) / _VBITS; this->_Myoff %= _VBITS; } else { // add non-negative increment - this->_Myoff += _Off; + this->_Myoff += static_cast<_Size_type>(_Off); this->_Myptr += this->_Myoff / _VBITS; this->_Myoff %= _VBITS; } return *this; } - _NODISCARD _Vb_const_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_const_iterator operator+(const difference_type _Off) const noexcept { _Vb_const_iterator _Tmp = *this; return _Tmp += _Off; } - _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_const_iterator& operator-=(const difference_type _Off) noexcept { return *this += -_Off; } - _NODISCARD _Vb_const_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_const_iterator operator-(const difference_type _Off) const noexcept { _Vb_const_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD difference_type operator-(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER difference_type operator-(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return static_cast(_VBITS * (this->_Myptr - _Right._Myptr)) + static_cast(this->_Myoff) - static_cast(_Right._Myoff); } - _NODISCARD const_reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator[](const difference_type _Off) const noexcept { return *(*this + _Off); } - _NODISCARD bool operator==(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator==(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return this->_Myptr == _Right._Myptr && this->_Myoff == _Right._Myoff; } - _NODISCARD bool operator!=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator!=(const _Vb_const_iterator& _Right) const noexcept { return !(*this == _Right); } - _NODISCARD bool operator<(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<(const _Vb_const_iterator& _Right) const noexcept { _Compat(_Right); return this->_Myptr < _Right._Myptr || (this->_Myptr == _Right._Myptr && this->_Myoff < _Right._Myoff); } - _NODISCARD bool operator>(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>(const _Vb_const_iterator& _Right) const noexcept { return _Right < *this; } - _NODISCARD bool operator<=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator<=(const _Vb_const_iterator& _Right) const noexcept { return !(_Right < *this); } - _NODISCARD bool operator>=(const _Vb_const_iterator& _Right) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool operator>=(const _Vb_const_iterator& _Right) const noexcept { return !(*this < _Right); } - void _Compat(const _Vb_const_iterator& _Right) const noexcept { // test for compatible iterator pair + _CONSTEXPR20_CONTAINER void _Compat(const _Vb_const_iterator& _Right) const noexcept { + // test for compatible iterator pair #if _ITERATOR_DEBUG_LEVEL == 0 (void) _Right; #else // _ITERATOR_DEBUG_LEVEL == 0 @@ -2041,13 +2122,14 @@ public: #if _ITERATOR_DEBUG_LEVEL != 0 using _Prevent_inheriting_unwrap = _Vb_const_iterator; - friend void _Verify_range(const _Vb_const_iterator& _First, const _Vb_const_iterator& _Last) noexcept { + friend _CONSTEXPR20_CONTAINER void _Verify_range( + const _Vb_const_iterator& _First, const _Vb_const_iterator& _Last) noexcept { // note _Compat check inside <= _STL_VERIFY(_First <= _Last, "vector iterator range transposed"); } #endif // _ITERATOR_DEBUG_LEVEL != 0 - void _Dec() noexcept { // decrement bit position + _CONSTEXPR20_CONTAINER void _Dec() noexcept { // decrement bit position #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Cont = static_cast(this->_Getcont()); _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); @@ -2062,7 +2144,7 @@ public: } } - void _Inc() noexcept { // increment bit position + _CONSTEXPR20_CONTAINER void _Inc() noexcept { // increment bit position #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Cont = static_cast(this->_Getcont()); _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); @@ -2080,7 +2162,7 @@ public: }; template -_NODISCARD _Vb_const_iterator<_Alvbase_wrapped> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vb_const_iterator<_Alvbase_wrapped> operator+( typename _Vb_const_iterator<_Alvbase_wrapped>::difference_type _Off, _Vb_const_iterator<_Alvbase_wrapped> _Right) noexcept { return _Right += _Off; @@ -2105,7 +2187,7 @@ public: using _Mybase::_Mybase; - _NODISCARD reference operator*() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator*() const noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 const auto _Cont = static_cast(this->_Getcont()); _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); @@ -2116,51 +2198,54 @@ public: return _Reft(*this); } - _Vb_iterator& operator++() noexcept { + // TRANSITION, DevCom-1331017 + _CONSTEXPR20_CONTAINER _Vb_iterator& operator=(const _Vb_iterator&) noexcept = default; + + _CONSTEXPR20_CONTAINER _Vb_iterator& operator++() noexcept { _Mybase::operator++(); return *this; } - _Vb_iterator operator++(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator operator++(int) noexcept { _Vb_iterator _Tmp = *this; _Mybase::operator++(); return _Tmp; } - _Vb_iterator& operator--() noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator--() noexcept { _Mybase::operator--(); return *this; } - _Vb_iterator operator--(int) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator operator--(int) noexcept { _Vb_iterator _Tmp = *this; _Mybase::operator--(); return _Tmp; } - _Vb_iterator& operator+=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator+=(const difference_type _Off) noexcept { _Mybase::operator+=(_Off); return *this; } - _NODISCARD _Vb_iterator operator+(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_iterator operator+(const difference_type _Off) const noexcept { _Vb_iterator _Tmp = *this; return _Tmp += _Off; } - _Vb_iterator& operator-=(const difference_type _Off) noexcept { + _CONSTEXPR20_CONTAINER _Vb_iterator& operator-=(const difference_type _Off) noexcept { _Mybase::operator-=(_Off); return *this; } using _Mybase::operator-; - _NODISCARD _Vb_iterator operator-(const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER _Vb_iterator operator-(const difference_type _Off) const noexcept { _Vb_iterator _Tmp = *this; return _Tmp -= _Off; } - _NODISCARD reference operator[](const difference_type _Off) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](const difference_type _Off) const noexcept { return *(*this + _Off); } @@ -2168,7 +2253,7 @@ public: }; template -_NODISCARD _Vb_iterator<_Alvbase_wrapped> operator+( +_NODISCARD _CONSTEXPR20_CONTAINER _Vb_iterator<_Alvbase_wrapped> operator+( typename _Vb_iterator<_Alvbase_wrapped>::difference_type _Off, _Vb_iterator<_Alvbase_wrapped> _Right) noexcept { return _Right += _Off; } @@ -2183,39 +2268,41 @@ public: using _Alvbase_wrapped = _Wrap_alloc<_Alvbase>; using size_type = typename _Alvbase_traits::size_type; - _Vb_val() noexcept(is_nothrow_default_constructible_v<_Vectype>) : _Myvec(), _Mysize(0) { + _CONSTEXPR20_CONTAINER _Vb_val() noexcept(is_nothrow_default_constructible_v<_Vectype>) : _Myvec(), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Alvbase>) + _CONSTEXPR20_CONTAINER _Vb_val(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Alvbase>) : _Myvec(static_cast<_Alvbase>(_Al)), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(size_type _Count, const bool& _Val) : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0)), _Mysize(0) { + _CONSTEXPR20_CONTAINER _Vb_val(size_type _Count, const bool& _Val) + : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0)), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(size_type _Count, const bool& _Val, const _Alloc& _Al) + _CONSTEXPR20_CONTAINER _Vb_val(size_type _Count, const bool& _Val, const _Alloc& _Al) : _Myvec(_Nw(_Count), static_cast<_Vbase>(_Val ? -1 : 0), static_cast<_Alvbase>(_Al)), _Mysize(0) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(const _Vb_val& _Right) : _Myvec(_Right._Myvec), _Mysize(_Right._Mysize) { + _CONSTEXPR20_CONTAINER _Vb_val(const _Vb_val& _Right) : _Myvec(_Right._Myvec), _Mysize(_Right._Mysize) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(const _Vb_val& _Right, const _Alloc& _Al) + _CONSTEXPR20_CONTAINER _Vb_val(const _Vb_val& _Right, const _Alloc& _Al) : _Myvec(_Right._Myvec, static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(_Vb_val&& _Right) noexcept(is_nothrow_move_constructible_v<_Vectype>) + _CONSTEXPR20_CONTAINER _Vb_val(_Vb_val&& _Right) noexcept(is_nothrow_move_constructible_v<_Vectype>) : _Myvec(_STD move(_Right._Myvec)), _Mysize(_STD exchange(_Right._Mysize, size_type{0})) { this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - _Vb_val(_Vb_val&& _Right, const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Vectype, _Vectype, _Alvbase>) + _CONSTEXPR20_CONTAINER _Vb_val(_Vb_val&& _Right, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Vectype, _Vectype, _Alvbase>) : _Myvec(_STD move(_Right._Myvec), static_cast<_Alvbase>(_Al)), _Mysize(_Right._Mysize) { if (_Right._Myvec.empty()) { // we took _Right's buffer, so zero out size @@ -2225,7 +2312,7 @@ public: this->_Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alvbase, _Getal())); } - ~_Vb_val() noexcept { + _CONSTEXPR20_CONTAINER ~_Vb_val() noexcept { #if _ITERATOR_DEBUG_LEVEL != 0 this->_Orphan_all(); auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alvbase, this->_Getal()); @@ -2233,15 +2320,15 @@ public: #endif // _ITERATOR_DEBUG_LEVEL != 0 } - _Alvbase& _Getal() noexcept { + _CONSTEXPR20_CONTAINER _Alvbase& _Getal() noexcept { return _Myvec._Getal(); } - const _Alvbase& _Getal() const noexcept { + _CONSTEXPR20_CONTAINER const _Alvbase& _Getal() const noexcept { return _Myvec._Getal(); } - static size_type _Nw(size_type _Count) noexcept { + static _CONSTEXPR20_CONTAINER size_type _Nw(size_type _Count) noexcept { return (_Count + _VBITS - 1) / _VBITS; } @@ -2281,41 +2368,44 @@ public: static const int _VBITS = _STD _VBITS; enum { _EEN_VBITS = _VBITS }; // helper for expression evaluator - vector() noexcept(is_nothrow_default_constructible_v<_Mybase>) // strengthened + _CONSTEXPR20_CONTAINER vector() noexcept(is_nothrow_default_constructible_v<_Mybase>) // strengthened : _Mybase() {} - explicit vector(const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Mybase, const _Alloc&>) // strengthened + _CONSTEXPR20_CONTAINER explicit vector(const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Mybase, const _Alloc&>) // strengthened : _Mybase(_Al) {} - explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, false, _Al) { + _CONSTEXPR20_CONTAINER explicit vector(_CRT_GUARDOVERFLOW size_type _Count, const _Alloc& _Al = _Alloc()) + : _Mybase(_Count, false, _Al) { _Trim(_Count); } - vector(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) + _CONSTEXPR20_CONTAINER vector(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val, const _Alloc& _Al = _Alloc()) : _Mybase(_Count, _Val, _Al) { _Trim(_Count); } - vector(const vector& _Right) : _Mybase(_Right) {} + _CONSTEXPR20_CONTAINER vector(const vector& _Right) : _Mybase(_Right) {} - vector(const vector& _Right, const _Alloc& _Al) : _Mybase(_Right, _Al) {} + _CONSTEXPR20_CONTAINER vector(const vector& _Right, const _Alloc& _Al) : _Mybase(_Right, _Al) {} template , int> = 0> - vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { + _CONSTEXPR20_CONTAINER vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mybase(_Al) { _BConstruct(_First, _Last); } template - void _BConstruct(_Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER void _BConstruct(_Iter _First, _Iter _Last) { insert(begin(), _First, _Last); } - vector(vector&& _Right) noexcept(is_nothrow_move_constructible_v<_Mybase>) // strengthened + _CONSTEXPR20_CONTAINER vector(vector&& _Right) noexcept(is_nothrow_move_constructible_v<_Mybase>) // strengthened : _Mybase(_STD move(_Right)) { this->_Swap_proxy_and_iterators(_Right); } - vector(vector&& _Right, const _Alloc& _Al) noexcept(is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) + _CONSTEXPR20_CONTAINER vector(vector&& _Right, const _Alloc& _Al) noexcept( + is_nothrow_constructible_v<_Mybase, _Mybase, const _Alloc&>) : _Mybase(_STD move(_Right), _Al) { if constexpr (!_Alvbase_traits::is_always_equal::value) { if (this->_Getal() != _Right._Getal()) { @@ -2328,13 +2418,13 @@ public: private: #if _ITERATOR_DEBUG_LEVEL != 0 - void _Move_assign(vector& _Right, _Equal_allocators) noexcept { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Equal_allocators) noexcept { this->_Myvec = _STD move(_Right._Myvec); this->_Mysize = _STD exchange(_Right._Mysize, size_type{0}); this->_Swap_proxy_and_iterators(_Right); } - void _Move_assign(vector& _Right, _Propagate_allocators) noexcept { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _Propagate_allocators) noexcept { using _Alproxy_type = _Rebind_alloc_t<_Alvbase, _Container_proxy>; if (this->_Getal() != _Right._Getal()) { // reload proxy // intentionally slams into noexcept on OOM, TRANSITION, VSO-466800 @@ -2353,7 +2443,7 @@ private: this->_Swap_proxy_and_iterators(_Right); } - void _Move_assign(vector& _Right, _No_propagate_allocators) { + _CONSTEXPR20_CONTAINER void _Move_assign(vector& _Right, _No_propagate_allocators) { this->_Myvec = _STD move(_Right._Myvec); this->_Mysize = _Right._Mysize; if (_Right._Myvec.empty()) { @@ -2368,7 +2458,7 @@ private: #endif // _ITERATOR_DEBUG_LEVEL != 0 public: - vector& operator=(vector&& _Right) noexcept(is_nothrow_move_assignable_v<_Mybase>) { + _CONSTEXPR20_CONTAINER vector& operator=(vector&& _Right) noexcept(is_nothrow_move_assignable_v<_Mybase>) { if (this != _STD addressof(_Right)) { #if _ITERATOR_DEBUG_LEVEL == 0 this->_Myvec = _STD move(_Right._Myvec); @@ -2382,7 +2472,7 @@ public: } template - decltype(auto) emplace_back(_Valty&&... _Val) { + _CONSTEXPR20_CONTAINER decltype(auto) emplace_back(_Valty&&... _Val) { bool _Tmp(_STD forward<_Valty>(_Val)...); push_back(_Tmp); @@ -2392,38 +2482,39 @@ public: } template - iterator emplace(const_iterator _Where, _Valty&&... _Val) { + _CONSTEXPR20_CONTAINER iterator emplace(const_iterator _Where, _Valty&&... _Val) { bool _Tmp(_STD forward<_Valty>(_Val)...); return insert(_Where, _Tmp); } - vector(initializer_list _Ilist, const _Alloc& _Al = allocator_type()) : _Mybase(0, false, _Al) { + _CONSTEXPR20_CONTAINER vector(initializer_list _Ilist, const _Alloc& _Al = allocator_type()) + : _Mybase(0, false, _Al) { insert(begin(), _Ilist.begin(), _Ilist.end()); } - vector& operator=(initializer_list _Ilist) { + _CONSTEXPR20_CONTAINER vector& operator=(initializer_list _Ilist) { assign(_Ilist.begin(), _Ilist.end()); return *this; } - void assign(initializer_list _Ilist) { + _CONSTEXPR20_CONTAINER void assign(initializer_list _Ilist) { assign(_Ilist.begin(), _Ilist.end()); } - iterator insert(const_iterator _Where, initializer_list _Ilist) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, initializer_list _Ilist) { return insert(_Where, _Ilist.begin(), _Ilist.end()); } - ~vector() noexcept {} + _CONSTEXPR20_CONTAINER ~vector() noexcept {} private: #if _ITERATOR_DEBUG_LEVEL != 0 - void _Copy_assign(const vector& _Right, false_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, false_type) { this->_Myvec = _Right._Myvec; this->_Mysize = _Right._Mysize; } - void _Copy_assign(const vector& _Right, true_type) { + _CONSTEXPR20_CONTAINER void _Copy_assign(const vector& _Right, true_type) { if (this->_Getal() == _Right._Getal()) { _Copy_assign(_Right, false_type{}); } else { @@ -2440,7 +2531,7 @@ private: #endif // _ITERATOR_DEBUG_LEVEL != 0 public: - vector& operator=(const vector& _Right) { + _CONSTEXPR20_CONTAINER vector& operator=(const vector& _Right) { if (this != _STD addressof(_Right)) { #if _ITERATOR_DEBUG_LEVEL == 0 this->_Myvec = _Right._Myvec; @@ -2454,70 +2545,70 @@ public: return *this; } - void reserve(_CRT_GUARDOVERFLOW size_type _Count) { + _CONSTEXPR20_CONTAINER void reserve(_CRT_GUARDOVERFLOW size_type _Count) { this->_Myvec.reserve(this->_Nw(_Count)); } - _NODISCARD size_type capacity() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type capacity() const noexcept { return this->_Myvec.capacity() * _VBITS; } - _NODISCARD iterator begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator begin() noexcept { return iterator(this->_Myvec.data(), this); } - _NODISCARD const_iterator begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator begin() const noexcept { return const_iterator(this->_Myvec.data(), this); } - _NODISCARD iterator end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator end() noexcept { return begin() + static_cast(this->_Mysize); } - _NODISCARD const_iterator end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator end() const noexcept { return begin() + static_cast(this->_Mysize); } - _NODISCARD const_iterator cbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cbegin() const noexcept { return begin(); } - _NODISCARD const_iterator cend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator cend() const noexcept { return end(); } - _NODISCARD const_reverse_iterator crbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crbegin() const noexcept { return rbegin(); } - _NODISCARD const_reverse_iterator crend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator crend() const noexcept { return rend(); } - _NODISCARD iterator _Unchecked_begin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Unchecked_begin() noexcept { return iterator(this->_Myvec.data(), this); } - _NODISCARD const_iterator _Unchecked_begin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator _Unchecked_begin() const noexcept { return const_iterator(this->_Myvec.data(), this); } - _NODISCARD iterator _Unchecked_end() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER iterator _Unchecked_end() noexcept { return _Unchecked_begin() + static_cast(this->_Mysize); } - _NODISCARD const_iterator _Unchecked_end() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_iterator _Unchecked_end() const noexcept { return _Unchecked_begin() + static_cast(this->_Mysize); } - void shrink_to_fit() { + _CONSTEXPR20_CONTAINER void shrink_to_fit() { if (this->_Myvec.capacity() != this->_Myvec.size()) { this->_Orphan_all(); this->_Myvec.shrink_to_fit(); } } - iterator _Make_iter(const_iterator _Where) noexcept { + _CONSTEXPR20_CONTAINER iterator _Make_iter(const_iterator _Where) noexcept { iterator _Tmp = begin(); if (0 < this->_Mysize) { _Tmp += _Where - begin(); @@ -2526,23 +2617,23 @@ public: return _Tmp; } - _NODISCARD reverse_iterator rbegin() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rbegin() noexcept { return reverse_iterator(end()); } - _NODISCARD const_reverse_iterator rbegin() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); } - _NODISCARD reverse_iterator rend() noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER reverse_iterator rend() noexcept { return reverse_iterator(begin()); } - _NODISCARD const_reverse_iterator rend() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); } - void resize(_CRT_GUARDOVERFLOW size_type _Newsize, bool _Val = false) { + _CONSTEXPR20_CONTAINER void resize(_CRT_GUARDOVERFLOW size_type _Newsize, bool _Val = false) { if (size() < _Newsize) { _Insert_n(end(), _Newsize - size(), _Val); } else if (_Newsize < size()) { @@ -2550,11 +2641,11 @@ public: } } - _NODISCARD size_type size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type size() const noexcept { return this->_Mysize; } - _NODISCARD size_type max_size() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_type max_size() const noexcept { constexpr auto _Diff_max = static_cast((numeric_limits::max)()); const size_type _Ints_max = this->_Myvec.max_size(); if (_Ints_max > _Diff_max / _VBITS) { // max_size bound by difference_type limits @@ -2565,15 +2656,15 @@ public: return _Ints_max * _VBITS; } - _NODISCARD bool empty() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER bool empty() const noexcept { return size() == 0; } - _NODISCARD allocator_type get_allocator() const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER allocator_type get_allocator() const noexcept { return static_cast(this->_Myvec.get_allocator()); } - _NODISCARD const_reference at(size_type _Off) const { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference at(size_type _Off) const { if (size() <= _Off) { _Xran(); } @@ -2581,7 +2672,7 @@ public: return (*this)[_Off]; } - _NODISCARD reference at(size_type _Off) { + _NODISCARD _CONSTEXPR20_CONTAINER reference at(size_type _Off) { if (size() <= _Off) { _Xran(); } @@ -2589,7 +2680,7 @@ public: return (*this)[_Off]; } - _NODISCARD const_reference operator[](size_type _Off) const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference operator[](size_type _Off) const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2599,7 +2690,7 @@ public: return *_It; } - _NODISCARD reference operator[](size_type _Off) noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER reference operator[](size_type _Off) noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(_Off < this->_Mysize, "vector subscript out of range"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2609,7 +2700,7 @@ public: return *_It; } - _NODISCARD reference front() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER reference front() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2617,7 +2708,7 @@ public: return *begin(); } - _NODISCARD const_reference front() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference front() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "front() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2625,7 +2716,7 @@ public: return *begin(); } - _NODISCARD reference back() noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER reference back() noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2633,7 +2724,7 @@ public: return *(end() - 1); } - _NODISCARD const_reference back() const noexcept /* strengthened */ { + _NODISCARD _CONSTEXPR20_CONTAINER const_reference back() const noexcept /* strengthened */ { #if _CONTAINER_DEBUG_LEVEL > 0 _STL_VERIFY(this->_Mysize != 0, "back() called on empty vector"); #endif // _CONTAINER_DEBUG_LEVEL > 0 @@ -2641,42 +2732,43 @@ public: return *(end() - 1); } - void push_back(const bool& _Val) { + _CONSTEXPR20_CONTAINER void push_back(const bool& _Val) { insert(end(), _Val); } - void pop_back() noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void pop_back() noexcept /* strengthened */ { erase(end() - 1); } template , int> = 0> - void assign(_Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER void assign(_Iter _First, _Iter _Last) { clear(); insert(begin(), _First, _Last); } - void assign(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { + _CONSTEXPR20_CONTAINER void assign(_CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { clear(); _Insert_n(begin(), _Count, _Val); } - iterator insert(const_iterator _Where, const bool& _Val) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, const bool& _Val) { return _Insert_n(_Where, static_cast(1), _Val); } - iterator insert(const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { + _CONSTEXPR20_CONTAINER iterator insert( + const_iterator _Where, _CRT_GUARDOVERFLOW size_type _Count, const bool& _Val) { return _Insert_n(_Where, _Count, _Val); } template , int> = 0> - iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { + _CONSTEXPR20_CONTAINER iterator insert(const_iterator _Where, _Iter _First, _Iter _Last) { difference_type _Off = _Where - begin(); _Insert(_Where, _First, _Last, _Iter_cat_t<_Iter>{}); return begin() + _Off; } template - void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, input_iterator_tag) { difference_type _Off = _Where - begin(); for (; _First != _Last; ++_First, (void) ++_Off) { @@ -2685,14 +2777,14 @@ public: } template - void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { + _CONSTEXPR20_CONTAINER void _Insert(const_iterator _Where, _Iter _First, _Iter _Last, forward_iterator_tag) { _Adl_verify_range(_First, _Last); auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); size_type _Off = _Insert_x(_Where, _Count); _Copy_unchecked(_Get_unwrapped(_First), _Get_unwrapped(_Last), begin() + static_cast(_Off)); } - iterator erase(const_iterator _Where_arg) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _Where_arg) noexcept /* strengthened */ { iterator _Where = _Make_iter(_Where_arg); difference_type _Off = _Where - begin(); @@ -2709,7 +2801,8 @@ public: return begin() + _Off; } - iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER iterator erase(const_iterator _First_arg, const_iterator _Last_arg) noexcept + /* strengthened */ { iterator _First = _Make_iter(_First_arg); iterator _Last = _Make_iter(_Last_arg); difference_type _Off = _First - begin(); @@ -2730,13 +2823,13 @@ public: return begin() + _Off; } - void clear() noexcept { + _CONSTEXPR20_CONTAINER void clear() noexcept { this->_Orphan_all(); this->_Myvec.clear(); this->_Mysize = 0; } - void flip() noexcept { // toggle all elements + _CONSTEXPR20_CONTAINER void flip() noexcept { // toggle all elements for (auto& _Elem : this->_Myvec) { _Elem = ~_Elem; } @@ -2744,7 +2837,7 @@ public: _Trim(this->_Mysize); } - void swap(vector& _Right) noexcept /* strengthened */ { + _CONSTEXPR20_CONTAINER void swap(vector& _Right) noexcept /* strengthened */ { if (this != _STD addressof(_Right)) { this->_Swap_proxy_and_iterators(_Right); this->_Myvec.swap(_Right._Myvec); @@ -2752,7 +2845,7 @@ public: } } - static void swap(reference _Left, reference _Right) noexcept { + static _CONSTEXPR20_CONTAINER void swap(reference _Left, reference _Right) noexcept { bool _Val = _Left; // NOT _STD swap _Left = _Right; _Right = _Val; @@ -2760,14 +2853,14 @@ public: friend hash>; - iterator _Insert_n(const_iterator _Where, size_type _Count, const bool& _Val) { + _CONSTEXPR20_CONTAINER iterator _Insert_n(const_iterator _Where, size_type _Count, const bool& _Val) { size_type _Off = _Insert_x(_Where, _Count); const auto _Result = begin() + static_cast(_Off); _STD fill(_Result, _Result + static_cast(_Count), _Val); return _Result; } - size_type _Insert_x(const_iterator _Where, size_type _Count) { + _CONSTEXPR20_CONTAINER size_type _Insert_x(const_iterator _Where, size_type _Count) { difference_type _Off = _Where - begin(); #if _ITERATOR_DEBUG_LEVEL == 2 @@ -2799,8 +2892,7 @@ public: } #if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range(size_type _Offlo, size_type _Offhi) const { - _Lockit _Lock(_LOCK_DEBUG); + _CONSTEXPR20_CONTAINER void _Orphan_range_unlocked(size_type _Offlo, size_type _Offhi) const { const auto _Base = this->_Myvec.data(); _Iterator_base12** _Pnext = &this->_Myproxy->_Myfirstiter; @@ -2816,11 +2908,24 @@ public: } } -#else // _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range(size_type, size_type) const {} + void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { + _Lockit _Lock(_LOCK_DEBUG); + _Orphan_range_unlocked(_Offlo, _Offhi); + } + + _CONSTEXPR20_CONTAINER void _Orphan_range(size_type _Offlo, size_type _Offhi) const { +#ifdef __cpp_lib_constexpr_dynamic_alloc + if (_STD is_constant_evaluated()) { + _Orphan_range_unlocked(_Offlo, _Offhi); + } else +#endif // __cpp_lib_constexpr_dynamic_alloc + { + _Orphan_range_locked(_Offlo, _Offhi); + } + } #endif // _ITERATOR_DEBUG_LEVEL == 2 - void _Trim(size_type _Size) { + _CONSTEXPR20_CONTAINER void _Trim(size_type _Size) { if (max_size() < _Size) { _Xlen(); // result too long } @@ -2847,12 +2952,14 @@ public: }; template -_NODISCARD bool operator==(const vector& _Left, const vector& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator==( + const vector& _Left, const vector& _Right) { return _Left.size() == _Right.size() && _Left._Myvec == _Right._Myvec; } template -_NODISCARD bool operator!=(const vector& _Left, const vector& _Right) { +_NODISCARD _CONSTEXPR20_CONTAINER bool operator!=( + const vector& _Left, const vector& _Right) { return !(_Left == _Right); } @@ -2869,12 +2976,12 @@ struct hash> { #if _HAS_CXX20 template -typename vector<_Ty, _Alloc>::size_type erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { +_CONSTEXPR20_CONTAINER typename vector<_Ty, _Alloc>::size_type erase(vector<_Ty, _Alloc>& _Cont, const _Uty& _Val) { return _Erase_remove(_Cont, _Val); } template -typename vector<_Ty, _Alloc>::size_type erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { +_CONSTEXPR20_CONTAINER typename vector<_Ty, _Alloc>::size_type erase_if(vector<_Ty, _Alloc>& _Cont, _Pr _Pred) { return _Erase_remove_if(_Cont, _Pass_fn(_Pred)); } #endif // _HAS_CXX20 @@ -2920,13 +3027,13 @@ _CONSTEXPR20 void _Fill_vbool(_FwdIt _First, _FwdIt _Last, const _Ty& _Val) { *_VbFirst = (*_VbFirst & _FirstDestMask) | (_FillVal & _FirstSourceMask); ++_VbFirst; -#ifdef __cpp_lib_is_constant_evaluated +#ifdef __cpp_lib_constexpr_dynamic_alloc if (_STD is_constant_evaluated()) { for (; _VbFirst != _VbLast; ++_VbFirst) { *_VbFirst = _FillVal; } } else -#endif // __cpp_lib_is_constant_evaluated +#endif // __cpp_lib_constexpr_dynamic_alloc { const auto _VbFirst_ch = reinterpret_cast(_VbFirst); const auto _VbLast_ch = reinterpret_cast(_VbLast); diff --git a/stl/inc/xmemory b/stl/inc/xmemory index 9550df6676a..c3fdd774d14 100644 --- a/stl/inc/xmemory +++ b/stl/inc/xmemory @@ -1212,8 +1212,8 @@ private: // MEMBER FUNCTIONS FOR _Container_base12 _CONSTEXPR20_CONTAINER void _Container_base12::_Orphan_all_unlocked() noexcept { - for (auto _Pnext = &_Myproxy->_Myfirstiter; *_Pnext; *_Pnext = (*_Pnext)->_Mynextiter) { - (*_Pnext)->_Myproxy = nullptr; + for (auto& _Pnext = _Myproxy->_Myfirstiter; _Pnext; _Pnext = _Pnext->_Mynextiter) { // TRANSITION, VSO-1269037 + _Pnext->_Myproxy = nullptr; } _Myproxy->_Myfirstiter = nullptr; } diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index d5d0f8f2e84..893be8074b9 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -181,6 +181,7 @@ // P0919R3 Heterogeneous Lookup For Unordered Containers // P0966R1 string::reserve() Should Not Shrink // P1001R2 execution::unseq +// P1004R2 constexpr std::vector // P1006R1 constexpr For pointer_traits::pointer_to() // P1007R3 assume_aligned() // P1020R1 Smart Pointer Creation With Default Initialization @@ -1202,6 +1203,10 @@ #define __cpp_lib_constexpr_tuple 201811L #define __cpp_lib_constexpr_utility 201811L +#if defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 +#define __cpp_lib_constexpr_vector 201907L +#endif // defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) + #ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support #define __cpp_lib_coroutine 201902L #endif // __cpp_impl_coroutine @@ -1284,7 +1289,7 @@ #endif // Functions that became constexpr in C++20 via P0980R1 or P1004R2 -#if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION:LLVM-48606 +#if defined(__cpp_lib_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 #define _CONSTEXPR20_CONTAINER constexpr #else #define _CONSTEXPR20_CONTAINER inline diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index e406827dbd4..5afeb945ccb 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -320,9 +320,6 @@ std/language.support/support.limits/support.limits.general/functional.version.pa std/language.support/support.limits/support.limits.general/iterator.version.pass.cpp FAIL std/language.support/support.limits/support.limits.general/memory.version.pass.cpp FAIL -# C++20 P1004R2 "constexpr std::vector" -std/language.support/support.limits/support.limits.general/vector.version.pass.cpp FAIL - # C++20 P1614R2 "Adding Spaceship <=> To The Library" std/language.support/support.limits/support.limits.general/compare.version.pass.cpp FAIL @@ -373,6 +370,16 @@ std/utilities/utility/pairs/pairs.pair/assign_rv_pair_U_V.pass.cpp:0 FAIL std/algorithms/alg.sorting/alg.sort/partial.sort/partial_sort.pass.cpp:0 FAIL std/algorithms/alg.sorting/alg.sort/partial.sort/partial_sort_comp.pass.cpp:0 FAIL +# VSO-1275530 "[constexpr] Temporaries created for functions do not have a ctor called (and have a redundant dtor)." +std/numerics/numeric.ops/exclusive.scan/exclusive_scan.pass.cpp:0 FAIL +std/numerics/numeric.ops/exclusive.scan/exclusive_scan_init_op.pass.cpp:0 FAIL +std/numerics/numeric.ops/inclusive.scan/inclusive_scan.pass.cpp:0 FAIL +std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op.pass.cpp:0 FAIL +std/numerics/numeric.ops/inclusive.scan/inclusive_scan_op_init.pass.cpp:0 FAIL +std/numerics/numeric.ops/transform.exclusive.scan/transform_exclusive_scan_init_bop_uop.pass.cpp:0 FAIL +std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop.pass.cpp:0 FAIL +std/numerics/numeric.ops/transform.inclusive.scan/transform_inclusive_scan_bop_uop_init.pass.cpp:0 FAIL + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -381,6 +388,9 @@ std/thread/macro.pass.cpp:1 FAIL # LLVM-46207 Clang's tgmath.h interferes with the UCRT's tgmath.h std/depr/depr.c.headers/tgmath_h.pass.cpp:1 FAIL +# LLVM-48606 "Clang rejects creation of struct with mutable member during constant evaluation" +std/language.support/support.limits/support.limits.general/vector.version.pass.cpp:1 FAIL + # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? diff --git a/tests/libcxx/skipped_tests.txt b/tests/libcxx/skipped_tests.txt index 9482df7db03..e54f1dfb276 100644 --- a/tests/libcxx/skipped_tests.txt +++ b/tests/libcxx/skipped_tests.txt @@ -320,9 +320,6 @@ language.support\support.limits\support.limits.general\functional.version.pass.c language.support\support.limits\support.limits.general\iterator.version.pass.cpp language.support\support.limits\support.limits.general\memory.version.pass.cpp -# C++20 P1004R2 "constexpr std::vector" -language.support\support.limits\support.limits.general\vector.version.pass.cpp - # C++20 P1614R2 "Adding Spaceship <=> To The Library" language.support\support.limits\support.limits.general\compare.version.pass.cpp @@ -373,6 +370,16 @@ utilities\utility\pairs\pairs.pair\assign_rv_pair_U_V.pass.cpp algorithms\alg.sorting\alg.sort\partial.sort\partial_sort.pass.cpp algorithms\alg.sorting\alg.sort\partial.sort\partial_sort_comp.pass.cpp +# VSO-1275530 "[constexpr] Temporaries created for functions do not have a ctor called (and have a redundant dtor)." +numerics\numeric.ops\exclusive.scan\exclusive_scan.pass.cpp +numerics\numeric.ops\exclusive.scan\exclusive_scan_init_op.pass.cpp +numerics\numeric.ops\inclusive.scan\inclusive_scan.pass.cpp +numerics\numeric.ops\inclusive.scan\inclusive_scan_op.pass.cpp +numerics\numeric.ops\inclusive.scan\inclusive_scan_op_init.pass.cpp +numerics\numeric.ops\transform.exclusive.scan\transform_exclusive_scan_init_bop_uop.pass.cpp +numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop.pass.cpp +numerics\numeric.ops\transform.inclusive.scan\transform_inclusive_scan_bop_uop_init.pass.cpp + # *** CLANG COMPILER BUGS *** # LLVM-33230 "Clang on Windows should define __STDCPP_THREADS__ to be 1" @@ -381,6 +388,9 @@ thread\macro.pass.cpp # LLVM-46207 Clang's tgmath.h interferes with the UCRT's tgmath.h depr\depr.c.headers\tgmath_h.pass.cpp +# LLVM-48606 "Clang rejects creation of struct with mutable member during constant evaluation" +language.support\support.limits\support.limits.general\vector.version.pass.cpp + # *** CLANG ISSUES, NOT YET ANALYZED *** # Clang doesn't enable sized deallocation by default. Should we add -fsized-deallocation or do something else? diff --git a/tests/std/test.lst b/tests/std/test.lst index 695d770af47..e99506d1251 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -260,6 +260,7 @@ tests\P0758R1_is_nothrow_convertible tests\P0768R1_spaceship_cpos tests\P0768R1_spaceship_operator tests\P0769R2_shift_left_shift_right +tests\P0784R7_library_machinery tests\P0784R7_library_support_for_more_constexpr_containers tests\P0811R3_midpoint_lerp tests\P0896R4_common_iterator @@ -379,6 +380,8 @@ tests\P0898R3_identity tests\P0912R5_coroutine tests\P0919R3_heterogeneous_unordered_lookup tests\P0966R1_string_reserve_should_not_shrink +tests\P1004R2_constexpr_vector +tests\P1004R2_constexpr_vector_bool tests\P1007R3_assume_aligned tests\P1020R1_smart_pointer_for_overwrite tests\P1023R0_constexpr_for_array_comparisons diff --git a/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp b/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp index 49726a50d6c..619ccd9a0f0 100644 --- a/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp +++ b/tests/std/tests/Dev10_816787_swap_vector_bool_elements/test.cpp @@ -17,6 +17,7 @@ int main() { assert(all_of(x.begin(), x.end(), is_false)); assert(all_of(y.begin(), y.end(), is_true)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 swap(x[12], y[34]); assert(all_of(x.begin(), x.begin() + 12, is_false)); @@ -26,4 +27,5 @@ int main() { assert(all_of(y.begin(), y.begin() + 34, is_true)); assert(!y[34]); assert(all_of(y.begin() + 35, y.end(), is_true)); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 } diff --git a/tests/std/tests/P0784R7_library_machinery/env.lst b/tests/std/tests/P0784R7_library_machinery/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0784R7_library_machinery/test.cpp b/tests/std/tests/P0784R7_library_machinery/test.cpp new file mode 100644 index 00000000000..80293a7a9ca --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -0,0 +1,150 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include + +#pragma warning(disable : 4582) // '%s': constructor is not implicitly called +#pragma warning(disable : 4583) // '%s': destructor is not implicitly called + +using namespace std; + +struct int_wrapper_copy { + constexpr int_wrapper_copy() = default; + constexpr int_wrapper_copy(const int v) : _val(v) {} + + constexpr int_wrapper_copy(const int_wrapper_copy& other) : _val(other._val) {} + constexpr int_wrapper_copy& operator=(const int_wrapper_copy& other) { + _val = other._val; + return *this; + } + + int_wrapper_copy(int_wrapper_copy&&) = delete; + int_wrapper_copy& operator=(int_wrapper_copy&&) = delete; + + constexpr bool operator==(const int_wrapper_copy&) const = default; + + int _val = 0; +}; + +struct int_wrapper_move { + constexpr int_wrapper_move() = default; + constexpr int_wrapper_move(const int v) : _val(v) {} + + int_wrapper_move(const int_wrapper_move&) = delete; + int_wrapper_move& operator=(const int_wrapper_move&) = delete; + + constexpr int_wrapper_move(int_wrapper_move&& other) : _val(exchange(other._val, -1)) {} + constexpr int_wrapper_move& operator=(int_wrapper_move&& other) { + _val = exchange(other._val, -1); + return *this; + } + + constexpr bool operator==(const int_wrapper_move&) const = default; + + int _val = 0; +}; + +static constexpr int_wrapper_copy expected_copy[] = {1, 2, 3, 4}; +static constexpr int_wrapper_move expected_move[] = {1, 2, 3, 4}; +static constexpr int_wrapper_move expected_after_move[] = {-1, -1, -1, -1}; + +_CONSTEXPR20_DYNALLOC bool test() { + { // _Copy_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4] = {5, 6, 7, 8}; + + const auto result = _Copy_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_copy*>); + assert(result == end(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } + + { // _Copy_backward_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4] = {5, 6, 7, 8}; + + const auto result = _Copy_backward_unchecked(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_copy*>); + assert(result == begin(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } + +#if defined(__cpp_constexpr_dynamic_alloc) + { // _Uninitialized_copy_unchecked + int_wrapper_copy input[] = {1, 2, 3, 4}; + int_wrapper_copy output[4]; + + const auto result = _Uninitialized_copy_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_copy*>); + assert(result == end(output)); + assert(equal(begin(expected_copy), end(expected_copy), begin(output), end(output))); + } +#endif // defined(__cpp_constexpr_dynamic_alloc) + + { // _Move_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const auto result = _Move_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == end(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + + { // _Move_backward_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const auto result = _Move_backward_unchecked(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == begin(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } + +#ifdef __cpp_lib_concepts + { // _Move_backward_common + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4] = {5, 6, 7, 8}; + + const auto result = ranges::_Move_backward_common(begin(input), end(input), end(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == begin(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } +#endif // __cpp_lib_concepts + +#if defined(__cpp_constexpr_dynamic_alloc) && (defined(__clang__) || defined(__EDG__)) // TRANSITION, DevCom-1333853 + { // _Uninitialized_move_unchecked + int_wrapper_move input[] = {1, 2, 3, 4}; + int_wrapper_move output[4]; + + const auto result = _Uninitialized_move_unchecked(begin(input), end(input), begin(output)); + static_assert(is_same_v, int_wrapper_move*>); + assert(result == end(output)); + assert(equal(begin(expected_move), end(expected_move), begin(output), end(output))); + if (is_constant_evaluated()) { + assert(equal(begin(input), end(input), begin(expected_after_move), end(expected_after_move))); + } + } +#endif // defined(__cpp_constexpr_dynamic_alloc) && (defined(__clang__) || defined(__EDG__)) + return true; +} + +int main() { + test(); + static_assert(test()); +} diff --git a/tests/std/tests/P1004R2_constexpr_vector/env.lst b/tests/std/tests/P1004R2_constexpr_vector/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P1004R2_constexpr_vector/test.cpp b/tests/std/tests/P1004R2_constexpr_vector/test.cpp new file mode 100644 index 00000000000..1d7358f0c94 --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -0,0 +1,727 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 +static constexpr int input[] = {0, 1, 2, 3, 4, 5}; +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) + +template +struct soccc_allocator { + using value_type = T; + + _CONSTEXPR20_CONTAINER soccc_allocator() noexcept = default; + _CONSTEXPR20_CONTAINER explicit soccc_allocator(const int id_) noexcept : id(id_), soccc_generation(0) {} + _CONSTEXPR20_CONTAINER explicit soccc_allocator(const int id_, const int soccc_generation_) noexcept + : id(id_), soccc_generation(soccc_generation_) {} + template + _CONSTEXPR20_CONTAINER soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id), soccc_generation(other.soccc_generation) {} + _CONSTEXPR20_CONTAINER soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id + 1), soccc_generation(other.soccc_generation) {} + + _CONSTEXPR20_CONTAINER soccc_allocator& operator=(const soccc_allocator&) noexcept { + return *this; + } + + _CONSTEXPR20_CONTAINER soccc_allocator select_on_container_copy_construction() const noexcept { + return soccc_allocator(id, soccc_generation + 1); + } + + template + _CONSTEXPR20_CONTAINER bool operator==(const soccc_allocator&) const noexcept { + return true; + } + + _CONSTEXPR20_CONTAINER T* allocate(const size_t n) { + return allocator{}.allocate(n); + } + + _CONSTEXPR20_CONTAINER void deallocate(T* const p, const size_t n) noexcept { + allocator{}.deallocate(p, n); + } + + template + _CONSTEXPR20_CONTAINER void construct(T* const p, Args&&... args) { + construct_at(p, forward(args)...); + } + + int id = 0; + int soccc_generation = 0; +}; + +using vec = vector>; + +_CONSTEXPR20_CONTAINER bool test_interface() { +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 + { // constructors + + // Non allocator constructors + vec size_default_constructed(5); + assert(size_default_constructed.size() == 5); +#ifndef __EDG__ // TRANSITION, VSO-1273296 + assert(all_of( + size_default_constructed.begin(), size_default_constructed.end(), [](const int val) { return val == 0; })); +#endif // __EDG__ + + vec size_value_constructed(5, 7); + assert(size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 + assert(all_of( + size_value_constructed.begin(), size_value_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + vec range_constructed(begin(input), end(input)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + vec initializer_list_constructed({2, 3, 4, 5}); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal( + initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + // special member functions + vec default_constructed; + assert(default_constructed.empty()); + vec copy_constructed(size_default_constructed); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + vec move_constructed(move(copy_constructed)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty + + vec copy_assigned = range_constructed; +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + vec move_assigned = move(copy_assigned); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(copy_assigned.empty()); // implementation-specific assumption that moved-from is empty + + // allocator constructors + soccc_allocator alloc(2, 3); + assert(alloc.id == 2); + assert(alloc.soccc_generation == 3); + + vec al_default_constructed(alloc); + assert(al_default_constructed.empty()); + assert(al_default_constructed.get_allocator().id == 4); + assert(al_default_constructed.get_allocator().soccc_generation == 3); + + vec al_copy_constructed(size_value_constructed, alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 + assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_copy_constructed.get_allocator().id == 4); + assert(al_copy_constructed.get_allocator().soccc_generation == 3); + + vec al_move_constructed(move(al_copy_constructed), alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 + assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_copy_constructed.empty()); // implementation-specific assumption that moved-from is empty + assert(al_move_constructed.get_allocator().id == 4); + assert(al_move_constructed.get_allocator().soccc_generation == 3); + + vec al_size_default_constructed(5, alloc); + assert(al_size_default_constructed.size() == 5); +#ifndef __EDG__ // TRANSITION, VSO-1273296 + assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), + [](const int val) { return val == 0; })); +#endif // __EDG__ + assert(al_size_default_constructed.get_allocator().id == 4); + assert(al_size_default_constructed.get_allocator().soccc_generation == 3); + + vec al_size_value_constructed(5, 7, alloc); + assert(al_size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 + assert(all_of(al_size_value_constructed.begin(), al_size_value_constructed.end(), + [](const int val) { return val == 7; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_size_value_constructed.get_allocator().id == 4); + assert(al_size_value_constructed.get_allocator().soccc_generation == 3); + + vec al_range_constructed(begin(input), end(input), alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(al_range_constructed.begin(), al_range_constructed.end(), begin(input), end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_range_constructed.get_allocator().id == 4); + assert(al_range_constructed.get_allocator().soccc_generation == 3); + + vec al_initializer_list_constructed({2, 3, 4, 5}, alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + assert(equal(al_initializer_list_constructed.begin(), al_initializer_list_constructed.end(), begin(input) + 2, + end(input))); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_initializer_list_constructed.get_allocator().id == 4); + assert(al_initializer_list_constructed.get_allocator().soccc_generation == 3); + } + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + { // assignment + vec range_constructed(begin(input), end(input)); + + vec copy_constructed; + copy_constructed = range_constructed; + assert(equal( + copy_constructed.begin(), copy_constructed.end(), range_constructed.begin(), range_constructed.end())); + + vec move_constructed; + move_constructed = move(copy_constructed); + assert(equal( + move_constructed.begin(), move_constructed.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty + + vec initializer_list_constructed; + initializer_list_constructed = {0, 1, 2, 3, 4, 5}; + assert( + equal(initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input), end(input))); + + vec assigned; + constexpr int expected_assign_value[] = {4, 4, 4, 4, 4}; + assigned.assign(5, 4); + assert(equal(assigned.begin(), assigned.end(), begin(expected_assign_value), end(expected_assign_value))); + + assigned.assign(begin(input), end(input)); + assert(equal(assigned.begin(), assigned.end(), begin(input), end(input))); + + constexpr int expected_assign_initializer[] = {2, 3, 4, 5}; + assigned.assign({2, 3, 4, 5}); + assert(equal( + assigned.begin(), assigned.end(), begin(expected_assign_initializer), end(expected_assign_initializer))); + } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + { // allocator + vec default_constructed; + const auto alloc = default_constructed.get_allocator(); + static_assert(is_same_v, soccc_allocator>); + assert(alloc.id == 1); + assert(alloc.soccc_generation == 0); + } + + { // iterators + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 + const auto b = range_constructed.begin(); + static_assert(is_same_v, vec::iterator>); + assert(*b == 0); + + const auto cb = range_constructed.cbegin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb == 0); + + const auto cb2 = const_range_constructed.begin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb2 == 0); + + const auto e = range_constructed.end(); + static_assert(is_same_v, vec::iterator>); + assert(*prev(e) == 5); + + const auto ce = range_constructed.cend(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce) == 5); + + const auto ce2 = const_range_constructed.end(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce2) == 5); + + const auto rb = range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*rb == 5); + + const auto crb = range_constructed.crbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb == 5); + + const auto crb2 = const_range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb2 == 5); + + const auto re = range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(re) == 0); + + const auto cre = range_constructed.crend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre) == 0); + + const auto cre2 = const_range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre2) == 0); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + } + + { // access + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + + const auto at = range_constructed.at(2); + static_assert(is_same_v, int>); + assert(at == 2); + + range_constructed.at(2) = 3; + + const auto at2 = range_constructed.at(2); + static_assert(is_same_v, int>); + assert(at2 == 3); + + const auto cat = const_range_constructed.at(2); + static_assert(is_same_v, int>); + assert(cat == 2); + + const auto op = range_constructed[3]; + static_assert(is_same_v, int>); + assert(op == 3); + + range_constructed[3] = 4; + const auto op2 = range_constructed[3]; + static_assert(is_same_v, int>); + assert(op2 == 4); + + const auto cop = const_range_constructed[3]; + static_assert(is_same_v, int>); + assert(cop == 3); + + const auto f = range_constructed.front(); + static_assert(is_same_v, int>); + assert(f == 0); + + const auto cf = const_range_constructed.front(); + static_assert(is_same_v, int>); + assert(cf == 0); + + const auto b = range_constructed.back(); + static_assert(is_same_v, int>); + assert(b == 5); + + const auto cb = const_range_constructed.back(); + static_assert(is_same_v, int>); + assert(cb == 5); + + const auto d = range_constructed.data(); + static_assert(is_same_v, int*>); + assert(*d == 0); + + const auto cd = const_range_constructed.data(); + static_assert(is_same_v, const int*>); + assert(*cd == 0); + } + + { // capacity + vec range_constructed(begin(input), end(input)); + + const auto e = range_constructed.empty(); + static_assert(is_same_v, bool>); + assert(!e); + + const auto s = range_constructed.size(); + static_assert(is_same_v, size_t>); + assert(s == size(input)); + + const auto ms = range_constructed.max_size(); + static_assert(is_same_v, size_t>); + assert(ms == static_cast(-1) / sizeof(int)); + + range_constructed.reserve(20); + + const auto c = range_constructed.capacity(); + static_assert(is_same_v, size_t>); + assert(c == 20); + + range_constructed.shrink_to_fit(); + + const auto c2 = range_constructed.capacity(); + static_assert(is_same_v, size_t>); + assert(c2 == 6); + } + + { // modifiers + vec range_constructed(begin(input), end(input)); + + vec cleared = range_constructed; + cleared.clear(); + assert(cleared.empty()); + assert(cleared.capacity() == range_constructed.capacity()); + + vec inserted; + +#ifndef __EDG__ // TRANSITION, VSO-1273386, VSO-1274387 + const int to_be_inserted = 3; + inserted.insert(inserted.begin(), to_be_inserted); + assert(inserted.size() == 1); + assert(inserted.front() == 3); + + const int to_be_inserted2 = 4; + inserted.insert(inserted.cbegin(), to_be_inserted2); + assert(inserted.size() == 2); + assert(inserted.front() == 4); + + inserted.insert(inserted.begin(), 1); + assert(inserted.size() == 3); + assert(inserted.front() == 1); + + inserted.insert(inserted.cbegin(), 2); + assert(inserted.size() == 4); + assert(inserted.front() == 2); +#endif // __EDG__ + +#ifndef __EDG__ // TRANSITION, VSO-1273381, VSO-1273296 + const auto it = inserted.insert(inserted.begin(), begin(input), end(input)); + assert(inserted.size() == 10); + assert(it == inserted.begin()); + + const auto it2 = inserted.insert(inserted.cbegin(), begin(input), end(input)); + assert(inserted.size() == 16); + assert(it2 == inserted.begin()); + + const auto it3 = inserted.insert(inserted.begin(), {2, 3, 4}); + assert(inserted.size() == 19); + assert(it3 == inserted.begin()); +#endif // __EDG__ + +#ifndef __EDG__ // TRANSITION, VSO-1274387, VSO-1273296 + inserted.insert(inserted.cbegin(), {2, 3, 4}); + assert(inserted.size() == 22); + + inserted.insert(inserted.begin(), 4, 11); + assert(inserted.size() == 26); + + vec emplaced; + emplaced.emplace(emplaced.cbegin(), 42); + assert(emplaced.size() == 1); + assert(emplaced.front() == 42); + + emplaced.emplace_back(43); + assert(emplaced.size() == 2); + assert(emplaced.back() == 43); + + emplaced.push_back(44); + assert(emplaced.size() == 3); + assert(emplaced.back() == 44); + + const int to_be_pushed = 45; + emplaced.push_back(to_be_pushed); + assert(emplaced.size() == 4); + assert(emplaced.back() == 45); + + emplaced.pop_back(); + assert(emplaced.size() == 3); + assert(emplaced.back() == 44); + + emplaced.resize(1); + assert(emplaced.size() == 1); + assert(emplaced.front() == 42); + + emplaced.swap(inserted); + assert(inserted.size() == 1); + assert(inserted.front() == 42); + assert(emplaced.size() == 26); + + emplaced.erase(emplaced.end() - 1); + assert(emplaced.size() == 25); + + emplaced.erase(emplaced.begin(), emplaced.begin() + 2); + assert(emplaced.size() == 23); +#endif // __EDG__ + } + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 + { // swap + vec first{2, 3, 4}; + vec second{5, 6, 7, 8}; + swap(first, second); + + constexpr int expected_first[] = {5, 6, 7, 8}; + constexpr int expected_second[] = {2, 3, 4}; + assert(equal(first.begin(), first.end(), begin(expected_first), end(expected_first))); + assert(equal(second.begin(), second.end(), begin(expected_second), end(expected_second))); + } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 + { // erase + vec erased{1, 2, 3, 4, 2, 3, 2}; + erase(erased, 2); + constexpr int expected_erased[] = {1, 3, 4, 3}; + assert(equal(erased.begin(), erased.end(), begin(expected_erased), end(expected_erased))); + + erase_if(erased, [](const int val) { return val < 4; }); + constexpr int expected_erase_if[] = {4}; + assert(equal(erased.begin(), erased.end(), begin(expected_erase_if), end(expected_erase_if))); + } +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + { // comparison + vec first(begin(input), end(input)); + vec second(begin(input), end(input)); + vec third{2, 3, 4}; + + const auto e = first == second; + static_assert(is_same_v, bool>); + assert(e); + + const auto ne = first != third; + static_assert(is_same_v, bool>); + assert(ne); + + const auto l = first < third; + static_assert(is_same_v, bool>); + assert(l); + + const auto le = first <= third; + static_assert(is_same_v, bool>); + assert(le); + + const auto g = first > third; + static_assert(is_same_v, bool>); + assert(!g); + + const auto ge = first >= third; + static_assert(is_same_v, bool>); + assert(!ge); + } +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) + return true; +} + +_CONSTEXPR20_CONTAINER bool test_iterators() { +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 + vec range_constructed(begin(input), end(input)); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 + { // increment + auto it = range_constructed.begin(); + assert(*++it == 1); + assert(*it++ == 1); + assert(*it == 2); + + auto cit = range_constructed.cbegin(); + assert(*++cit == 1); + assert(*cit++ == 1); + assert(*cit == 2); + } + + { // advance + auto it = range_constructed.begin() + 2; + assert(*it == 2); + it += 2; + assert(*it == 4); + + auto cit = range_constructed.cbegin() + 2; + assert(*cit == 2); + cit += 2; + assert(*cit == 4); + } + + { // decrement + auto it = range_constructed.end(); + assert(*--it == 5); + assert(*it-- == 5); + assert(*it == 4); + + auto cit = range_constructed.cend(); + assert(*--cit == 5); + assert(*cit-- == 5); + assert(*cit == 4); + } + + { // advance back + auto it = range_constructed.end() - 2; + assert(*it == 4); + it -= 2; + assert(*it == 2); + + auto cit = range_constructed.cend() - 2; + assert(*cit == 4); + cit -= 2; + assert(*cit == 2); + } + + { // difference + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.end(); + assert(it2 - it1 == ssize(input)); + + const auto cit1 = range_constructed.cbegin(); + const auto cit2 = range_constructed.cend(); + assert(cit2 - cit1 == ssize(input)); + + assert(it2 - cit1 == ssize(input)); + assert(cit2 - it1 == ssize(input)); + } + + { // comparison + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.begin(); + const auto it3 = range_constructed.end(); + + assert(it1 == it2); + assert(it1 != it3); + assert(it1 < it3); + assert(it1 <= it3); + assert(it3 > it1); + assert(it3 >= it1); + } + + { // access + const auto it = range_constructed.begin() + 2; + it[2] = 3; + assert(range_constructed[4] == 3); + + const auto cit = range_constructed.cbegin() + 2; + assert(cit[2] == 3); + + vector> vec2 = {{1, 2}, {2, 3}}; + const auto it2 = vec2.begin(); + assert(it2->second == 2); + + const auto cit2 = vec2.cbegin(); + assert(cit2->first == 1); + } + +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) + return true; +} + +_CONSTEXPR20_CONTAINER bool test_growth() { +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.resize(1003); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.resize(8000); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.push_back(47); + + assert(v.size() == 1001); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + vector l(3, 47); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + v.insert(v.end(), l.begin(), l.end()); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + vector l(7000, 47); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1274387 + v.insert(v.end(), l.begin(), l.end()); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + +#ifndef __EDG__ // TRANSITION, VSO-1273386, VSO-1274387 + v.insert(v.end(), 3, 47); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); +#endif // __EDG__ + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + +#ifndef __EDG__ // TRANSITION, VSO-1273386, VSO-1274387 + v.insert(v.end(), 7000, 47); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); +#endif // __EDG__ + } +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) + return true; +} + +int main() { + test_interface(); + test_iterators(); + test_growth(); +#ifdef __cpp_lib_constexpr_vector + static_assert(test_interface()); + static_assert(test_iterators()); + static_assert(test_growth()); +#endif // __cpp_lib_constexpr_vector +} diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/env.lst b/tests/std/tests/P1004R2_constexpr_vector_bool/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp new file mode 100644 index 00000000000..c1441f02775 --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -0,0 +1,646 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +#if defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1270433, VSO-1275530 +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-const-variable" // TRANSITION, LLVM-48606 +#endif // __clang__ +static constexpr bool input[] = {true, false, true, true, false, true}; +static constexpr bool input_flipped[] = {false, true, false, false, true, false}; +#ifdef __clang__ +#pragma clang diagnostic pop +#endif // __clang__ +#endif // defined(MSVC_INTERNAL_TESTING) || defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + +template +struct soccc_allocator { + using value_type = T; + + _CONSTEXPR20_DYNALLOC soccc_allocator() noexcept = default; + _CONSTEXPR20_DYNALLOC explicit soccc_allocator(const int id_) noexcept : id(id_), soccc_generation(0) {} + _CONSTEXPR20_DYNALLOC explicit soccc_allocator(const int id_, const int soccc_generation_) noexcept + : id(id_), soccc_generation(soccc_generation_) {} + template + _CONSTEXPR20_DYNALLOC soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id), soccc_generation(other.soccc_generation) {} + _CONSTEXPR20_DYNALLOC soccc_allocator(const soccc_allocator& other) noexcept + : id(other.id + 1), soccc_generation(other.soccc_generation) {} + + _CONSTEXPR20_DYNALLOC soccc_allocator& operator=(const soccc_allocator&) noexcept { + return *this; + } + + _CONSTEXPR20_DYNALLOC soccc_allocator select_on_container_copy_construction() const noexcept { + return soccc_allocator(id, soccc_generation + 1); + } + + template + _CONSTEXPR20_DYNALLOC bool operator==(const soccc_allocator&) const noexcept { + return true; + } + + _CONSTEXPR20_DYNALLOC T* allocate(const size_t n) { + return allocator{}.allocate(n); + } + + _CONSTEXPR20_DYNALLOC void deallocate(T* const p, const size_t n) noexcept { + allocator{}.deallocate(p, n); + } + + template + _CONSTEXPR20_DYNALLOC void construct(T* const p, Args&&... args) { + construct_at(p, forward(args)...); + } + + int id = 0; + int soccc_generation = 0; +}; + +using vec = vector>; + +_CONSTEXPR20_CONTAINER bool test_interface() { +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 + { // constructors + +// Non allocator constructors +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec size_default_constructed(5); + assert(size_default_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(all_of( + size_default_constructed.begin(), size_default_constructed.end(), [](const bool val) { return !val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ + +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec size_value_constructed(5, true); + assert(size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert( + all_of(size_value_constructed.begin(), size_value_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); + + vec initializer_list_constructed({true, true, false, true}); + assert(equal( + initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + // special member functions +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec default_constructed; + assert(default_constructed.empty()); + vec copy_constructed(size_default_constructed); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + vec move_constructed(move(copy_constructed)); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty +#endif // __EDG__ + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 +#ifndef __EDG__ // TRANSITION, VSO-1274387, VSO-1273296 + vec copy_assigned = range_constructed; + assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); + + vec move_assigned = move(copy_assigned); + assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_assigned.empty()); // implementation-specific assumption that moved-from is empty +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + // allocator constructors + soccc_allocator alloc(2, 3); + assert(alloc.id == 2); + assert(alloc.soccc_generation == 3); + +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec al_default_constructed(alloc); + assert(al_default_constructed.empty()); + assert(al_default_constructed.get_allocator().id == 4); + assert(al_default_constructed.get_allocator().soccc_generation == 3); + + vec al_copy_constructed(size_value_constructed, alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_copy_constructed.get_allocator().id == 4); + assert(al_copy_constructed.get_allocator().soccc_generation == 3); + + vec al_move_constructed(move(al_copy_constructed), alloc); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_copy_constructed.empty()); // implementation-specific assumption that moved-from is empty + assert(al_move_constructed.get_allocator().id == 4); + assert(al_move_constructed.get_allocator().soccc_generation == 3); + + vec al_size_default_constructed(5, alloc); + assert(al_size_default_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), + [](const bool val) { return !val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_size_default_constructed.get_allocator().id == 4); + assert(al_size_default_constructed.get_allocator().soccc_generation == 3); + + vec al_size_value_constructed(5, true, alloc); + assert(al_size_value_constructed.size() == 5); +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273296 + assert(all_of( + al_size_value_constructed.begin(), al_size_value_constructed.end(), [](const bool val) { return val; })); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + assert(al_size_value_constructed.get_allocator().id == 4); + assert(al_size_value_constructed.get_allocator().soccc_generation == 3); +#endif // __EDG__ + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273365 +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec al_range_constructed(begin(input), end(input), alloc); + assert(equal(al_range_constructed.begin(), al_range_constructed.end(), begin(input), end(input))); + assert(al_range_constructed.get_allocator().id == 4); + assert(al_range_constructed.get_allocator().soccc_generation == 3); +#endif // __EDG__ + +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec al_initializer_list_constructed({true, true, false, true}, alloc); + assert(equal(al_initializer_list_constructed.begin(), al_initializer_list_constructed.end(), begin(input) + 2, + end(input))); + assert(al_initializer_list_constructed.get_allocator().id == 4); + assert(al_initializer_list_constructed.get_allocator().soccc_generation == 3); +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + } + + { // assignment +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + + vec copy_constructed; + copy_constructed = range_constructed; + assert(equal( + copy_constructed.begin(), copy_constructed.end(), range_constructed.begin(), range_constructed.end())); + + vec move_constructed; + move_constructed = move(copy_constructed); + assert(equal( + move_constructed.begin(), move_constructed.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_constructed.empty()); // implementation-specific assumption that moved-from is empty + + vec initializer_list_constructed; + initializer_list_constructed = {true, false, true, true, false, true}; + assert( + equal(initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input), end(input))); + + vec assigned; + constexpr bool expected_assign_value[] = {true, true, true, true, true}; + assigned.assign(5, true); + assert(equal(assigned.begin(), assigned.end(), begin(expected_assign_value), end(expected_assign_value))); + + assigned.assign(begin(input), end(input)); + assert(equal(assigned.begin(), assigned.end(), begin(input), end(input))); + + constexpr bool expected_assign_initializer[] = {true, false, true, true, false, true}; + assigned.assign({true, false, true, true, false, true}); + assert(equal( + assigned.begin(), assigned.end(), begin(expected_assign_initializer), end(expected_assign_initializer))); +#endif // __EDG__ + } + + { // allocator +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec default_constructed; + const auto alloc = default_constructed.get_allocator(); + static_assert(is_same_v, soccc_allocator>); + assert(alloc.id == 1); + assert(alloc.soccc_generation == 0); +#endif // __EDG__ + } + + { // iterators +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 + const auto b = range_constructed.begin(); + static_assert(is_same_v, vec::iterator>); + assert(*b); + + const auto cb = range_constructed.cbegin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb); + + const auto cb2 = const_range_constructed.begin(); + static_assert(is_same_v, vec::const_iterator>); + assert(*cb2); + + const auto e = range_constructed.end(); + static_assert(is_same_v, vec::iterator>); + assert(*prev(e)); + + const auto ce = range_constructed.cend(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce)); + + const auto ce2 = const_range_constructed.end(); + static_assert(is_same_v, vec::const_iterator>); + assert(*prev(ce2)); + + const auto rb = range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*rb); + + const auto crb = range_constructed.crbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb); + + const auto crb2 = const_range_constructed.rbegin(); + static_assert(is_same_v, reverse_iterator>); + assert(*crb2); + + const auto re = range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(re)); + + const auto cre = range_constructed.crend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre)); + + const auto cre2 = const_range_constructed.rend(); + static_assert(is_same_v, reverse_iterator>); + assert(*prev(cre2)); +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ + } + + { // access +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + const vec const_range_constructed(begin(input), end(input)); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 + const auto at = range_constructed.at(2); + static_assert(is_same_v, _Iter_ref_t>); + assert(at); + + range_constructed.at(2) = false; + + const auto at2 = range_constructed.at(2); + static_assert(is_same_v, _Iter_ref_t>); + assert(at2 == false); + + const auto cat = const_range_constructed.at(2); + static_assert(is_same_v, _Iter_ref_t>); + assert(cat); + + const auto op = range_constructed[3]; + static_assert(is_same_v, _Iter_ref_t>); + assert(op); + + range_constructed[3] = true; + const auto op2 = range_constructed[3]; + static_assert(is_same_v, _Iter_ref_t>); + assert(op2); + + const auto cop = const_range_constructed[3]; + static_assert(is_same_v, _Iter_ref_t>); + assert(cop); + + const auto f = range_constructed.front(); + static_assert(is_same_v, _Iter_ref_t>); + assert(f); + + const auto cf = const_range_constructed.front(); + static_assert(is_same_v, _Iter_ref_t>); + assert(cf); + + const auto b = range_constructed.back(); + static_assert(is_same_v, _Iter_ref_t>); + assert(b); + + const auto cb = const_range_constructed.back(); + static_assert(is_same_v, _Iter_ref_t>); + assert(cb); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // __EDG__ + } + + { // capacity +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + + const auto e = range_constructed.empty(); + static_assert(is_same_v, bool>); + assert(e == false); + + const auto s = range_constructed.size(); + static_assert(is_same_v, size_t>); + assert(s == size(input)); + + const auto ms = range_constructed.max_size(); + static_assert(is_same_v, size_t>); + assert(ms == static_cast(numeric_limits::max())); + + range_constructed.reserve(20); + + const auto c = range_constructed.capacity(); + static_assert(is_same_v, size_t>); + assert(c == 32); + + range_constructed.shrink_to_fit(); + + const auto c2 = range_constructed.capacity(); + static_assert(is_same_v, size_t>); + assert(c2 == 32); +#endif // __EDG__ + } + + { // modifiers +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + + vec flipped = range_constructed; + flipped.flip(); + assert(flipped.size() == 6); + assert(equal(flipped.begin(), flipped.end(), begin(input_flipped), end(input_flipped))); + // {true, false, true, true, false, true}; + + vec cleared = range_constructed; + cleared.clear(); + assert(cleared.empty()); + assert(cleared.capacity() == range_constructed.capacity()); + + vec inserted; + + const bool to_be_inserted = true; + inserted.insert(inserted.begin(), to_be_inserted); + assert(inserted.size() == 1); + assert(inserted.front()); + + const bool to_be_inserted2 = false; + inserted.insert(inserted.cbegin(), to_be_inserted2); + assert(inserted.size() == 2); + assert(inserted.front() == false); + + inserted.insert(inserted.begin(), true); + assert(inserted.size() == 3); + assert(inserted.front()); + + inserted.insert(inserted.cbegin(), false); + assert(inserted.size() == 4); + assert(inserted.front() == false); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 + const auto it = inserted.insert(inserted.begin(), begin(input), end(input)); + assert(inserted.size() == 10); + assert(it == inserted.begin()); + + const auto it2 = inserted.insert(inserted.cbegin(), begin(input), end(input)); + assert(inserted.size() == 16); + assert(it2 == inserted.begin()); + + const auto it3 = inserted.insert(inserted.begin(), {true, false, true}); + assert(inserted.size() == 19); + assert(it3 == inserted.begin()); +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 + + inserted.insert(inserted.cbegin(), {false, true, false}); + assert(inserted.size() == 22); + + inserted.insert(inserted.cbegin(), 3, true); + assert(inserted.size() == 25); + + vec emplaced; + emplaced.emplace(emplaced.cbegin(), false); + assert(emplaced.size() == 1); + assert(emplaced.front() == false); + + emplaced.emplace_back(true); + assert(emplaced.size() == 2); + assert(emplaced.back()); + + emplaced.push_back(false); + assert(emplaced.size() == 3); + assert(emplaced.back() == false); + + const bool to_be_pushed = true; + emplaced.push_back(to_be_pushed); + assert(emplaced.size() == 4); + assert(emplaced.back()); + + emplaced.pop_back(); + assert(emplaced.size() == 3); + assert(emplaced.back() == false); + + emplaced.resize(1); + assert(emplaced.size() == 1); + assert(emplaced.front() == false); + + emplaced.swap(inserted); + assert(inserted.size() == 1); + assert(inserted.front() == false); + assert(emplaced.size() == 25); + + emplaced.erase(emplaced.end() - 1); + assert(emplaced.size() == 24); + + emplaced.erase(emplaced.begin(), emplaced.begin() + 2); + assert(emplaced.size() == 22); +#endif // __EDG__ + } + + { // swap +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec first{true, false, true}; + vec second{false, false, true, false}; + swap(first, second); + + constexpr bool expected_first[] = {false, false, true, false}; + constexpr bool expected_second[] = {true, false, true}; + assert(equal(first.begin(), first.end(), begin(expected_first), end(expected_first))); + assert(equal(second.begin(), second.end(), begin(expected_second), end(expected_second))); +#endif // __EDG__ + } + + { // erase +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec erased{false, false, true, false, true}; + erase(erased, false); + constexpr bool expected_erased[] = {true, true}; + assert(equal(erased.begin(), erased.end(), begin(expected_erased), end(expected_erased))); + + vec erased_if{false, false, true, false, true}; + erase_if(erased_if, [](const bool val) { return val; }); + constexpr bool expected_erase_if[] = {false, false, false}; + assert(equal(erased_if.begin(), erased_if.end(), begin(expected_erase_if), end(expected_erase_if))); +#endif // __EDG__ + } + + { // comparison +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec first(begin(input), end(input)); + vec second(begin(input), end(input)); + vec third{true, false, true}; + + const auto e = first == second; + static_assert(is_same_v, bool>); + assert(e); + + const auto ne = first != third; + static_assert(is_same_v, bool>); + assert(ne); + + const auto l = first < third; + static_assert(is_same_v, bool>); + assert(!l); + + const auto le = first <= third; + static_assert(is_same_v, bool>); + assert(!le); + + const auto g = first > third; + static_assert(is_same_v, bool>); + assert(g); + + const auto ge = first >= third; + static_assert(is_same_v, bool>); + assert(ge); +#endif // __EDG__ + } +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) + + return true; +} + +_CONSTEXPR20_CONTAINER bool test_iterators() { +#if defined(__EDG__) \ + || _ITERATOR_DEBUG_LEVEL != 2 // || defined(MSVC_INTERNAL_TESTING) // TRANSITION, VSO-1270433, VSO-1275530 +#ifndef __EDG__ // TRANSITION, VSO-1274387 + vec range_constructed(begin(input), end(input)); + +#if !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 // TRANSITION, VSO-1273381 + { // increment + auto it = range_constructed.begin(); + assert(*++it == false); + assert(*it++ == false); + assert(*it); + + auto cit = range_constructed.cbegin(); + assert(*++cit == false); + assert(*cit++ == false); + assert(*cit); + } + + { // advance + auto it = range_constructed.begin() + 2; + assert(*it); + it += 2; + assert(*it == false); + + auto cit = range_constructed.cbegin() + 2; + assert(*cit); + cit += 2; + assert(*cit == false); + } + + { // decrement + auto it = range_constructed.end(); + assert(*--it); + assert(*it--); + assert(*it == false); + + auto cit = range_constructed.cend(); + assert(*--cit); + assert(*cit--); + assert(*cit == false); + } + + { // advance back + auto it = range_constructed.end() - 2; + assert(*it == false); + it -= 2; + assert(*it); + + auto cit = range_constructed.cend() - 2; + assert(*cit == false); + cit -= 2; + assert(*cit); + } + + { // difference + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.end(); + assert(it2 - it1 == ssize(input)); + + const auto cit1 = range_constructed.cbegin(); + const auto cit2 = range_constructed.cend(); + assert(cit2 - cit1 == ssize(input)); + + assert(it2 - cit1 == ssize(input)); + assert(cit2 - it1 == ssize(input)); + } + + { // comparison + const auto it1 = range_constructed.begin(); + const auto it2 = range_constructed.begin(); + const auto it3 = range_constructed.end(); + + assert(it1 == it2); + assert(it1 != it3); + assert(it1 < it3); + assert(it1 <= it3); + assert(it3 > it1); + assert(it3 >= it1); + } + + { // access + const auto it = range_constructed.begin() + 2; + it[2] = false; + assert(range_constructed[4] == false); + + const auto cit = range_constructed.cbegin() + 2; + assert(cit[2] == false); + } +#endif // __EDG__ +#endif // !defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 +#endif // defined(__EDG__) || _ITERATOR_DEBUG_LEVEL != 2 || defined(MSVC_INTERNAL_TESTING) + + return true; +} + +int main() { + test_interface(); + test_iterators(); +#ifdef __cpp_lib_constexpr_vector + static_assert(test_interface()); + static_assert(test_iterators()); +#endif // __cpp_lib_constexpr_vector +} 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 b0f604ebbca..f4ab60d8fcc 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 @@ -523,6 +523,20 @@ STATIC_ASSERT(__cpp_lib_constexpr_utility == 201811L); #endif #endif +#if _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && !defined(__clang__) // TRANSITION, LLVM-48606 +#ifndef __cpp_lib_constexpr_vector +#error __cpp_lib_constexpr_vector is not defined +#elif __cpp_lib_constexpr_vector != 201907L +#error __cpp_lib_constexpr_vector is not 201907L +#else +STATIC_ASSERT(__cpp_lib_constexpr_vector == 201907L); +#endif +#else +#ifdef __cpp_lib_constexpr_vector +#error __cpp_lib_constexpr_vector is defined +#endif +#endif + #if _HAS_CXX20 && defined(__cpp_impl_coroutine) // TRANSITION, Clang coroutine support #ifndef __cpp_lib_coroutine #error __cpp_lib_coroutine is not defined