diff --git a/stl/inc/vector b/stl/inc/vector index fe53326da9f..fcddc91663d 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -37,161 +37,199 @@ 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 { + _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"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 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"); - _STL_VERIFY( - _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't dereference value-initialized vector iterator"); + _STL_VERIFY( + _Mycont->_Myfirst <= _Ptr && _Ptr < _Mycont->_Mylast, "can't dereference out of range vector iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 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"); - _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't increment value-initialized vector iterator"); + _STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 ++_Ptr; 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"); - _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Ptr, "can't decrement value-initialized vector iterator"); + _STL_VERIFY(_Mycont->_Myfirst < _Ptr, "can't decrement vector iterator before begin"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 --_Ptr; 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 - const auto _Mycont = static_cast(this->_Getcont()); - _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); - if (_Off < 0) { - _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); - } +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(this->_Getcont()); + _STL_VERIFY(_Off == 0 || _Ptr, "cannot seek value-initialized vector iterator"); + if (_Off < 0) { + _STL_VERIFY(_Off >= _Mycont->_Myfirst - _Ptr, "cannot seek vector iterator before begin"); + } - if (_Off > 0) { - _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); + if (_Off > 0) { + _STL_VERIFY(_Off <= _Mycont->_Mylast - _Ptr, "cannot seek vector iterator after end"); + } } #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 - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); + } #endif // _ITERATOR_DEBUG_LEVEL == 0 } #if _ITERATOR_DEBUG_LEVEL != 0 - friend 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"); + friend _CONSTEXPR20_CONTAINER void _Verify_range( + const _Vector_const_iterator& _First, const _Vector_const_iterator& _Last) noexcept { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY( + _First._Getcont() == _Last._Getcont(), "vector iterators in range are from different containers"); + _STL_VERIFY(_First._Ptr <= _Last._Ptr, "vector iterator range transposed"); + } } #endif // _ITERATOR_DEBUG_LEVEL != 0 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 +237,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; } @@ -217,12 +255,17 @@ struct pointer_traits<_Vector_const_iterator<_Myvec>> { // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an // iterator. - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); + } } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -248,71 +291,83 @@ public: using _Mybase::_Mybase; - _NODISCARD reference operator*() const noexcept { + _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 +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + 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; } @@ -330,12 +385,17 @@ struct pointer_traits<_Vector_iterator<_Myvec>> { // capacity() of 0 is not. This function cannot distinguish those two cases, so it incorrectly does not diagnose // the latter. In practice, this isn't a significant problem since to_address returns nullptr for such an // iterator. - const auto _Mycont = static_cast(_Iter._Getcont()); - if (_Mycont) { - _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, - "can't convert out-of-range vector iterator to pointer"); - } else { - _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Mycont = static_cast(_Iter._Getcont()); + if (_Mycont) { + _STL_VERIFY(_Mycont->_Myfirst <= _Iter._Ptr && _Iter._Ptr <= _Mycont->_Mylast, + "can't convert out-of-range vector iterator to pointer"); + } else { + _STL_VERIFY(!_Iter._Ptr, "can't convert invalid vector iterator to pointer"); + } } #endif // _ITERATOR_DEBUG_LEVEL != 0 @@ -372,19 +432,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 +462,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 +_CONSTEXPR20_CONTAINER 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 +_CONSTEXPR20_CONTAINER _Ty* _Unfancy_maybe_null(_Ty* _Ptr) noexcept { // do nothing for plain pointers return _Ptr; } @@ -445,17 +506,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 +532,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 +555,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 +568,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 +577,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 +603,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 +621,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 +648,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 +657,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 +667,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 +687,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 +733,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 +742,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 +752,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 +770,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 +786,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,14 +841,20 @@ 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; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Oldlast >= _Whereptr, - "vector emplace iterator outside range"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst + && _Oldlast >= _Whereptr, + "vector emplace iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Oldlast != _My_data._Myend) { @@ -801,15 +877,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; @@ -819,8 +896,14 @@ public: const pointer _Oldfirst = _My_data._Myfirst; const pointer _Oldlast = _Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, - "vector insert iterator outside range"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY( + _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _Oldlast >= _Whereptr, + "vector insert iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 const auto _Whereoff = static_cast(_Whereptr - _Oldfirst); @@ -883,7 +966,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 +992,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,14 +1101,19 @@ 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; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst && _My_data._Mylast >= _Whereptr, - "vector insert iterator outside range"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _Oldfirst + && _My_data._Mylast >= _Whereptr, + "vector insert iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 _Adl_verify_range(_First, _Last); @@ -1034,11 +1122,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 +1155,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 +1185,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 +1198,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_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { 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 +1261,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 +1269,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 +1305,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 +1335,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 +1366,24 @@ private: _Change_array(_Newvec, _Size, _Newcapacity); } - void _Clear_and_reserve_geometric(const size_type _Newsize) { +#if _ITERATOR_DEBUG_LEVEL != 0 + 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_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _Check_all_orphaned_locked(); + } + } +#endif // _ITERATOR_DEBUG_LEVEL != 0 + + _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 +1391,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 +1413,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 +1424,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,29 +1437,40 @@ 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); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_My_data._Myfirst != _Mylast, "vector empty before pop"); + _Orphan_range(_Mylast - 1, _Mylast); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 _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; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY( - _Where._Getcont() == _STD addressof(_My_data) && _Whereptr >= _My_data._Myfirst && _Mylast > _Whereptr, - "vector erase iterator outside range"); - _Orphan_range(_Whereptr, _Mylast); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _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 _Move_unchecked(_Whereptr + 1, _Mylast, _Whereptr); @@ -1357,7 +1479,7 @@ public: 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; @@ -1365,9 +1487,14 @@ public: pointer& _Mylast = _My_data._Mylast; #if _ITERATOR_DEBUG_LEVEL == 2 - _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) - && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, - "vector erase iterator outside range"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_First._Getcont() == _STD addressof(_My_data) && _Last._Getcont() == _STD addressof(_My_data) + && _Firstptr >= _My_data._Myfirst && _Lastptr >= _Firstptr && _Mylast >= _Lastptr, + "vector erase iterator outside range"); + } #endif // _ITERATOR_DEBUG_LEVEL == 2 if (_Firstptr != _Lastptr) { // something to do, invalidate iterators @@ -1381,7 +1508,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; @@ -1392,130 +1519,140 @@ public: } 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( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 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( - _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY( + _Pos < static_cast(_My_data._Mylast - _My_data._Myfirst), "vector subscript out of range"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 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 +1661,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,87 +1670,109 @@ 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"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 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"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "front() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 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"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 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"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(_My_data._Myfirst != _My_data._Mylast, "back() called on empty vector"); + } #endif // _CONTAINER_DEBUG_LEVEL > 0 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 +1790,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 +1806,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 +1824,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 +1844,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,10 +1870,9 @@ 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 + void _Orphan_range_locked(pointer _First, pointer _Last) const { _Lockit _Lock(_LOCK_DEBUG); - _Iterator_base12** _Pnext = &_Mypair._Myval2._Myproxy->_Myfirstiter; while (*_Pnext) { const auto _Pnextptr = static_cast(**_Pnext)._Ptr; @@ -1724,25 +1883,33 @@ private: *_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 { + _CONSTEXPR20_CONTAINER void _Orphan_range(pointer _First, pointer _Last) const { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _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 +1925,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 +1980,21 @@ 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 { + _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 +2012,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,33 +2034,38 @@ 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"); - _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) <= static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 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,142 +2089,165 @@ public: using pointer = const_reference*; using reference = const_reference; - _Vb_const_iterator() = default; + _CONSTEXPR20_CONTAINER _Vb_const_iterator() = default; - _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept : _Mybase(_Ptr, 0, _Mypvbool) {} + _CONSTEXPR20_CONTAINER _Vb_const_iterator(const _Vbase* _Ptr, const _Container_base* _Mypvbool) noexcept + : _Mybase(_Ptr, 0, _Mypvbool) {} - _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"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 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()); - _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); - const auto _Start_offset = this->_Total_off(_Cont); - if (_Off < 0) { - _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); - } else if (0 < _Off) { - _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), - "cannot seek vector iterator after end"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + if (_Off != 0) { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot seek value-initialized vector iterator"); + const auto _Start_offset = this->_Total_off(_Cont); + if (_Off < 0) { + _STL_VERIFY(-_Start_offset <= _Off, "cannot seek vector iterator before begin"); + } else if (0 < _Off) { + _STL_VERIFY(_Off <= static_cast<_Difference_type>(_Cont->_Mysize - _Start_offset), + "cannot seek vector iterator after end"); + } } } #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 - _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _STL_VERIFY(this->_Getcont() == _Right._Getcont(), "vector iterators incompatible"); + } #endif // _ITERATOR_DEBUG_LEVEL } #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"); - _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot decrement value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) > 0, "cannot decrement vector begin iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 if (this->_Myoff != 0) { @@ -2062,12 +2258,17 @@ 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"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "cannot increment vector end iterator"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot increment value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "cannot increment vector end iterator"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 if (this->_Myoff < _VBITS - 1) { @@ -2080,7 +2281,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,62 +2306,67 @@ 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"); - _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), - "vector iterator not dereferenceable"); +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + const auto _Cont = static_cast(this->_Getcont()); + _STL_VERIFY(_Cont, "cannot dereference value-initialized vector iterator"); + _STL_VERIFY(this->_Total_off(_Cont) < static_cast<_Difference_type>(_Cont->_Mysize), + "vector iterator not dereferenceable"); + } #endif // _ITERATOR_DEBUG_LEVEL != 0 return _Reft(*this); } - _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--() 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 +2374,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 +2389,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 +2433,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 +2441,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 +2489,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 +2539,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 +2564,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 +2579,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 +2593,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 +2603,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 +2652,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 +2666,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 +2738,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 +2762,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 +2777,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 +2793,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 +2801,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 +2811,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 +2821,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 +2829,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 +2837,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 +2845,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 +2853,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 +2898,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 +2922,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 +2944,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 +2958,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 +2966,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 +2974,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,7 +3013,7 @@ public: } #if _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range(size_type _Offlo, size_type _Offhi) const { + void _Orphan_range_locked(size_type _Offlo, size_type _Offhi) const { _Lockit _Lock(_LOCK_DEBUG); const auto _Base = this->_Myvec.data(); @@ -2816,11 +3030,17 @@ public: } } -#else // _ITERATOR_DEBUG_LEVEL == 2 - void _Orphan_range(size_type, size_type) const {} + _CONSTEXPR20_CONTAINER void _Orphan_range(size_type _Offlo, size_type _Offhi) const { +#ifdef __cpp_lib_is_constant_evaluated + if (!_STD is_constant_evaluated()) +#endif // __cpp_lib_is_constant_evaluated + { + _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 +3067,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); } @@ -2862,19 +3084,19 @@ struct hash> { _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef vector _ARGUMENT_TYPE_NAME; _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS typedef size_t _RESULT_TYPE_NAME; - _NODISCARD size_t operator()(const vector& _Keyval) const noexcept { + _NODISCARD _CONSTEXPR20_CONTAINER size_t operator()(const vector& _Keyval) const noexcept { return _Hash_array_representation(_Keyval._Myvec.data(), _Keyval._Myvec.size()); } }; #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 diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 72b2d93e095..94033b70d71 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -178,6 +178,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 @@ -1195,6 +1196,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 // __cpp_constexpr_dynamic_alloc && !__clang__ + #ifdef __cpp_impl_coroutine // TRANSITION, Clang coroutine support #define __cpp_lib_coroutine 201902L #endif // __cpp_impl_coroutine diff --git a/tests/std/test.lst b/tests/std/test.lst index 014d2c798d4..9ec33bcb17e 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -254,6 +254,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 @@ -370,6 +371,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/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..b5dd430f7c5 --- /dev/null +++ b/tests/std/tests/P0784R7_library_machinery/test.cpp @@ -0,0 +1,147 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#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; + } + + constexpr int_wrapper_copy(int_wrapper_copy&&) = delete; + constexpr 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){}; + + constexpr int_wrapper_move(const int_wrapper_move&) = delete; + constexpr 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}; + +constexpr 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 _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) + { // _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 // _HAS_CXX20 && 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 _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) && defined(__clang__) + { // _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 // _HAS_CXX20 && defined(__cpp_constexpr_dynamic_alloc) + 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..99942d10401 --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector/test.cpp @@ -0,0 +1,638 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +static constexpr int input[] = {0, 1, 2, 3, 4, 5}; + +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& other) const noexcept { + return id == other.id; + } + + template + _CONSTEXPR20_DYNALLOC bool operator!=(const soccc_allocator& other) const noexcept { + return id != other.id; + } + + _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, std::forward(args)...); + } + + int id = 0; + int soccc_generation = 0; +}; + +using vec = vector>; + +_CONSTEXPR20_DYNALLOC bool test_interface() { + { // constructors + + // Non allocator constructors + vec size_default_constructed(5); + assert(size_default_constructed.size() == 5); + assert(all_of( + size_default_constructed.begin(), size_default_constructed.end(), [](const int val) { return val == 0; })); + + vec size_value_constructed(5, 7); + assert(size_value_constructed.size() == 5); + assert(all_of( + size_value_constructed.begin(), size_value_constructed.end(), [](const int val) { return val == 7; })); + + vec range_constructed(begin(input), end(input)); + assert(equal(range_constructed.begin(), range_constructed.end(), begin(input), end(input))); + + vec initializer_list_constructed({2, 3, 4, 5}); + assert(equal( + initializer_list_constructed.begin(), initializer_list_constructed.end(), begin(input) + 2, end(input))); + + // special member functions + vec default_constructed; + vec copy_constructed(size_default_constructed); + assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + + vec move_constructed(move(copy_constructed)); + assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + assert(copy_constructed.empty()); + + vec copy_assigned = range_constructed; + assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); + + vec move_assigned = std::move(copy_assigned); + assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_assigned.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); + assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const int val) { return val == 7; })); + 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); + assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const int val) { return val == 7; })); + assert(al_copy_constructed.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); + assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), + [](const int val) { return val == 0; })); + 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); + assert(all_of(al_size_value_constructed.begin(), al_size_value_constructed.end(), + [](const int val) { return val == 7; })); + 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); + 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); + + vec al_initializer_list_constructed({2, 3, 4, 5}, 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); + } + + { // 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()); + + 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))); + } + + { // 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)); + + 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); + } + + { // 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, std::size_t>); + assert(s == size(input)); + + const auto ms = range_constructed.max_size(); + static_assert(is_same_v, std::size_t>); + assert(ms == static_cast(-1) / 4); + + range_constructed.reserve(20); + + const auto c = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c == 20); + + range_constructed.shrink_to_fit(); + + const auto c2 = range_constructed.capacity(); + static_assert(is_same_v, std::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; + + 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); + + 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()); + + inserted.insert(inserted.cbegin(), {2, 3, 4}); + assert(inserted.size() == 22); + + 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() == 22); + } + + { // 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))); + } + + { // 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))); + } + + { // 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); + } + return true; +} + +_CONSTEXPR20_DYNALLOC bool test_iterators() { + vec range_constructed(begin(input), end(input)); + + { // 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); + + std::vector> vec2 = {{1, 2}, {2, 3}}; + const auto it2 = vec2.begin(); + assert(it2->second == 2); + + const auto cit2 = vec2.cbegin(); + assert(cit2->first == 1); + } + + return true; +} + +_CONSTEXPR20_DYNALLOC bool test_growth() { + { + 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); + + v.insert(v.end(), l.begin(), l.end()); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + vector l(7000, 47); + + v.insert(v.end(), l.begin(), l.end()); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.insert(v.end(), 3, 47); + + assert(v.size() == 1003); + assert(v.capacity() == 1500); + } + + { + vector v(1000, 1729); + + assert(v.size() == 1000); + assert(v.capacity() == 1000); + + v.insert(v.end(), 7000, 47); + + assert(v.size() == 8000); + assert(v.capacity() == 8000); + } + 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..c13ba554c0c --- /dev/null +++ b/tests/std/tests/P1004R2_constexpr_vector_bool/test.cpp @@ -0,0 +1,538 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +static constexpr bool input[] = {true, false, true, true, false, true}; + +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& other) const noexcept { + return id == other.id; + } + + template + _CONSTEXPR20_DYNALLOC bool operator!=(const soccc_allocator& other) const noexcept { + return id != other.id; + } + + _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, std::forward(args)...); + } + + int id = 0; + int soccc_generation = 0; +}; + +using vec = vector>; + +_CONSTEXPR20_DYNALLOC bool test_interface() { + { // constructors + + // Non allocator constructors + vec size_default_constructed(5); + assert(size_default_constructed.size() == 5); + assert(all_of( + size_default_constructed.begin(), size_default_constructed.end(), [](const bool val) { return !val; })); + + vec size_value_constructed(5, true); + assert(size_value_constructed.size() == 5); + assert( + all_of(size_value_constructed.begin(), size_value_constructed.end(), [](const bool val) { return val; })); + + 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))); + + // special member functions + vec default_constructed; + vec copy_constructed(size_default_constructed); + assert(equal(copy_constructed.begin(), copy_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + + vec move_constructed(move(copy_constructed)); + assert(equal(move_constructed.begin(), move_constructed.end(), size_default_constructed.begin(), + size_default_constructed.end())); + assert(copy_constructed.empty()); + + vec copy_assigned = range_constructed; + assert(equal(copy_assigned.begin(), copy_assigned.end(), range_constructed.begin(), range_constructed.end())); + + vec move_assigned = std::move(copy_assigned); + assert(equal(move_assigned.begin(), move_assigned.end(), range_constructed.begin(), range_constructed.end())); + assert(copy_assigned.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); + assert(all_of(al_copy_constructed.begin(), al_copy_constructed.end(), [](const bool val) { return val; })); + 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); + assert(all_of(al_move_constructed.begin(), al_move_constructed.end(), [](const bool val) { return val; })); + assert(al_copy_constructed.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); + assert(all_of(al_size_default_constructed.begin(), al_size_default_constructed.end(), + [](const bool val) { return !val; })); + 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); + assert(all_of( + al_size_value_constructed.begin(), al_size_value_constructed.end(), [](const bool val) { return val; })); + 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); + 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); + + 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); + } + + { // 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()); + + 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))); + } + + { // 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)); + + 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)); + } + + { // 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, _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); + } + + { // capacity + 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, std::size_t>); + assert(s == size(input)); + + const auto ms = range_constructed.max_size(); + static_assert(is_same_v, std::size_t>); + assert(ms == static_cast(std::numeric_limits::max())); + + range_constructed.reserve(20); + + const auto c = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c == 32); + + range_constructed.shrink_to_fit(); + + const auto c2 = range_constructed.capacity(); + static_assert(is_same_v, std::size_t>); + assert(c2 == 32); + } + + { // 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; + + 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); + + 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()); + + inserted.insert(inserted.cbegin(), {false, true, false}); + assert(inserted.size() == 22); + + 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() == 22); + } + + { // swap + 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))); + } + + { // erase + 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))); + } + + { // comparison + 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); + } + return true; +} + +_CONSTEXPR20_DYNALLOC bool test_iterators() { + vec range_constructed(begin(input), end(input)); + + { // 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); + + std::vector> vec2 = {{false, true}, {true, false}}; + const auto it2 = vec2.begin(); + assert(it2->second); + + const auto cit2 = vec2.cbegin(); + assert(cit2->first == false); + } + + 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 +}