From 3e6a2ffffe49e9bade6be725c17500e32a020a1d Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Mon, 18 Nov 2019 19:37:53 +0100 Subject: [PATCH 01/52] Basic implementation --- stl/inc/memory | 384 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 378 insertions(+), 6 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 46d7f7ede4a..93556c65206 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -13,6 +13,8 @@ #include #include #include +#include +#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -1251,11 +1253,45 @@ private: _Owner._Call_deleter = false; } - template - friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); + template +#if _HAS_CXX20 + requires (!_STD is_array_v<_Ty>) +#endif // _HAS_CXX20 + friend shared_ptr<_Ty> make_shared(_Types&&... _Args); - template - friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); +#if _HAS_CXX20 + template requires _STD is_unbounded_array_v<_Ty> + friend shared_ptr<_Ty> make_shared(size_t _Count); + + template requires _STD is_unbounded_array_v<_Ty> + friend shared_ptr<_Ty> make_shared(size_t _Count, const _STD remove_extent_t<_Ty>& _Val); + + template requires _STD is_bounded_array_v<_Ty> + friend shared_ptr<_Ty> make_shared(); + + template requires _STD is_bounded_array_v<_Ty> + friend shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val); +#endif // _HAS_CXX20 + + template +#if _HAS_CXX20 + requires (!_STD is_array_v<_Ty>) +#endif // _HAS_CXX20 + friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + +#if _HAS_CXX20 + template requires _STD is_unbounded_array_v<_Ty> + friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, size_t _Count); + + template requires _STD is_unbounded_array_v<_Ty> + friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val); + + template requires _STD is_bounded_array_v<_Ty> + friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg); + + template requires _STD is_bounded_array_v<_Ty> + friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, const _STD remove_extent_t<_Ty>& _Val); +#endif // _HAS_CXX20 template void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px @@ -1504,6 +1540,113 @@ private: } }; +#if _HAS_CXX20 +template +void _Uninitialized_copy_md(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { + if constexpr (_STD rank_v<_Ty> > 0) { + for (size_t _It = 0; _It < _Size; ++_It) + _Uninitialized_copy_md(_In[_It], _Out[_It]); + } else { + _STD uninitialized_copy_n(_In, _Size, _Out); + } +} + +template +void _Uninitialized_value_construct_md_n(_Ty* _Out, size_t _Size) { + if constexpr (_STD rank_v<_Ty> > 0) { + for (size_t _It = 0; _It < _Size; ++_It) + _Uninitialized_value_construct_md_n(_Out[_It], _STD extent_v<_Ty>); + } else { + _Uninitialized_value_construct_n_unchecked1(_Out, _Size); + } +} + +template +void _Reverse_destroy_md_n(_Ty* _Arr, size_t _Size) { + size_t _It = _Size; + do { + --_It; + if constexpr (_STD rank_v<_Ty> > 0) { + _Reverse_destroy_md_n(_Arr[_It], _STD extent_v<_Ty>); + } else { + _Destroy_in_place(_Arr[_It]); + } + } while (_It > 0); +} + +// CLASS TEMPLATE _Ref_count_unbounded_array +template +class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array in control block, no allocator +public: + explicit _Ref_count_unbounded_array(size_t _Count) : _Ref_count_base(), _Size(_Count) { + _Uninitialized_value_construct_md_n(_Get_ptr(), _Size); + } + + explicit _Ref_count_unbounded_array(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) : _Ref_count_base(), _Size(_Count) { + if constexpr (_STD rank_v<_Ty> > 1) { + for (size_t _It = 0; _It < _Size; ++_It) + _Uninitialized_copy_md(_Val, _Get_ptr()[_It]); + } else { + _STD uninitialized_fill_n(_Get_ptr(), _Size, _Val); + } + } + + ~_Ref_count_unbounded_array() { + // nothing to do, _Storage was already destroyed in _Destroy + } + + size_t _Size; + + auto _Get_ptr() { + return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + _STD max(sizeof(*this), alignof(_Ty))); + } +private: + virtual void _Destroy() noexcept override { // destroy managed resource + _Reverse_destroy_md_n(_Get_ptr(), _Size); + } + + virtual void _Delete_this() noexcept override { // destroy self + using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), _STD max(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + this->~_Ref_count_unbounded_array(); + delete[] reinterpret_cast<_Storage*>(this); + } +}; + +// CLASS TEMPLATE _Ref_count_bounded_array +template +class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in control block, no allocator +public: + explicit _Ref_count_bounded_array() : _Ref_count_base(), _Storage() { + + } + + explicit _Ref_count_bounded_array(const _STD remove_extent_t<_Ty>& _Val) : _Ref_count_base() { + if constexpr (_STD rank_v<_Ty> > 1) { + for (size_t _It = 0; _It < _STD extent_v<_Ty>; ++_It) + _Uninitialized_copy_md(_Val, _Storage._Value[_It]); + } else { + _STD uninitialized_fill_n(_Storage._Value, _STD extent_v<_Ty>, _Val); + } + } + + ~_Ref_count_bounded_array() { + // nothing to do, _Storage was already destroyed in _Destroy + } + + union { + _Wrap<_Ty> _Storage; + }; + +private: + virtual void _Destroy() noexcept override { // destroy managed resource + _Destroy_in_place(_Storage); + } + + virtual void _Delete_this() noexcept override { // destroy self + delete this; + } +}; +#endif // _HAS_CXX20 // CLASS TEMPLATE _Ebco_base template && !is_final_v<_Ty>> @@ -1578,18 +1721,193 @@ private: } }; +#if _HAS_CXX20 +template +void _Uninitialized_copy_md_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], const _Alloc& _Al) { + if constexpr (_STD rank_v<_Ty> > 0) { + for (size_t _It = 0; _It < _Size; ++_It) + _Uninitialized_copy_md_al(_In[_It], _Out[_It], _Al); + } else { + _Uninitialized_copy(_In, _In + _Size, _Out, _Al); + } +} + +template +void _Uninitialized_value_construct_md_n_al(_Ty* _Out, size_t _Size, const _Alloc& _Al) { + if constexpr (_STD rank_v<_Ty> > 0) { + for (size_t _It = 0; _It < _Size; ++_It) + _Uninitialized_value_construct_md_n_al(_Out[_It], _STD extent_v<_Ty>, _Al); + } else { + _Uninitialized_value_construct_n(_Out, _Size, _Al); + } +} + +template +void _Reverse_destroy_md_n_al(_Ty* _Arr, size_t _Size, const _Alloc& _Al) { + size_t _It = _Size; + do { + --_It; + if constexpr (_STD rank_v<_Ty> > 0) { + _Reverse_destroy_md_n_al(_Arr[_It], _STD extent_v<_Ty>, _Al); + } else { + allocator_traits::destroy(_Al, _Arr + _It); + } + } while (_It > 0); +} + +// CLASS TEMPLATE _Ref_count_unbounded_array_alloc +template +class __declspec(empty_bases) _Ref_count_unbounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { + // handle reference counting for object in control block, allocator +public: + explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, size_t _Count) + : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { + _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); + _Uninitialized_value_construct_md_n_al(_Get_ptr(), _Size, _Alty); + } + + explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) + : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { + _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); + if constexpr (_STD rank_v<_Ty> > 1) { + for (size_t _It = 0; _It < _Size; ++_It) + _Uninitialized_copy_md_al(_Val, _Get_ptr()[_It], _Alty); + } else { + _Uninitialized_fill_n(_Get_ptr(), _Size, _Val, _Alty); + } + } + + size_t _Size; + + auto _Get_ptr() { + return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + _STD max(sizeof(*this), alignof(_Ty))); + } +private: + ~_Ref_count_unbounded_array_alloc() { + // nothing to do; _Storage._Value already destroyed by _Destroy() + } + + virtual void _Destroy() noexcept override { // destroy managed resource + _Maybe_rebind_alloc_t<_Alloc, _STD remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Reverse_destroy_md_n_al(_Get_ptr(), _Size, _Alty); + } + + virtual void _Delete_this() noexcept override { // destroy self + constexpr size_t _Max_alignment = _STD max(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); + using _Storage = _STD aligned_storage_t<_Max_alignment, _Max_alignment>; + constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(*this) / sizeof(_Storage), size_t(1)); + constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); + this->~_Ref_count_unbounded_array_alloc(); + allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), static_cast(ceil(_Size * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size); + } +}; + +// CLASS TEMPLATE _Ref_count_bounded_array_alloc +template +class __declspec(empty_bases) _Ref_count_bounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { + // handle reference counting for object in control block, allocator +public: + explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) + : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { + _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); + _Uninitialized_value_construct_md_n_al(_Storage._Value, _STD extent_v<_Ty>, _Alty); + } + + explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg, const _STD remove_extent_t<_Ty>& _Val) + : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { + _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); + if constexpr (_STD rank_v<_Ty> > 1) { + for (size_t _It = 0; _It < _STD extent_v<_Ty>; ++_It) + _Uninitialized_copy_md_al(_Val, _Storage._Value[_It], _Alty); + } else { + _Uninitialized_fill_n(_Storage._Value, _STD extent_v<_Ty>, _Val, _Alty); + } + } + + union { + _Wrap<_Ty> _Storage; + }; + +private: + ~_Ref_count_bounded_array_alloc() { + // nothing to do; _Storage._Value already destroyed by _Destroy() + } + + virtual void _Destroy() noexcept override { // destroy managed resource + _Maybe_rebind_alloc_t<_Alloc, _STD remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Reverse_destroy_md_n_al(_Storage._Value, _STD extent_v<_Ty>, _Alty); + } + + virtual void _Delete_this() noexcept override { // destroy self + _Rebind_alloc_t<_Alloc, _Ref_count_bounded_array_alloc> _Al(this->_Get_val()); + this->~_Ref_count_bounded_array_alloc(); + _Deallocate_plain(_Al, this); + } +}; +#endif // _HAS_CXX20 + // FUNCTION TEMPLATE make_shared template -_NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr +#if _HAS_CXX20 + requires (!_STD is_array_v<_Ty>) +#endif // _HAS_CXX20 +_NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_STD addressof(_Rx->_Storage._Value), _Rx); return _Ret; } +#if _HAS_CXX20 +template requires _STD is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared(size_t _Count) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array<_Ty>; + using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); + new(_Rx) _Refc(_Count); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); + return _Ret; +} + +template requires _STD is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array<_Ty>; + using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); + new(_Rx) _Refc(_Count, _Val); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); + return _Ret; +} + +template requires _STD is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array + const auto _Rx = new _Ref_count_bounded_array<_Ty>(); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); + return _Ret; +} + +template requires _STD is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array + const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); + return _Ret; +} +#endif // _HAS_CXX20 // FUNCTION TEMPLATE allocate_shared template -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr +#if _HAS_CXX20 + requires (!_STD is_array_v<_Ty>) +#endif // _HAS_CXX20 +_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether // allocator::construct sees T or const T when _Ty is const qualified) using _Refoa = _Ref_count_obj_alloc2, _Alloc>; @@ -1604,6 +1922,60 @@ _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) return _Ret; } +#if _HAS_CXX20 +template requires _STD is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; + using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); + new(_Rx) _Refc(_Al, _Count); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); + return _Ret; +} + +template requires _STD is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; + using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); + new(_Rx) _Refc(_Al, _Count, _Val); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); + return _Ret; +} + +template requires _STD is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al) { // make a shared_ptr to a bounded array + using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; + using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; + _Alblock _Rebound(_Al); + const auto _Rx = _Rebound.allocate(1); + new(_Rx) _Refc(_Al); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); + return _Ret; +} + +template requires _STD is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array + using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; + using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; + _Alblock _Rebound(_Al); + const auto _Rx = _Rebound.allocate(1); + new(_Rx) _Refc(_Al, _Val); + shared_ptr<_Ty> _Ret; + _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); + return _Ret; +} +#endif // _HAS_CXX20 + // CLASS TEMPLATE weak_ptr template class weak_ptr : public _Ptr_base<_Ty> { // class for pointer to reference counted resource From 52de1ba1c31789c17aec44327f7b53855b18f81c Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Mon, 18 Nov 2019 21:18:01 +0100 Subject: [PATCH 02/52] Update yvals_core.h --- stl/inc/yvals_core.h | 1 + 1 file changed, 1 insertion(+) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 9412cc07aec..fb878fb2c2a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -36,6 +36,7 @@ // P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type // P0653R2 to_address() // P0655R1 visit() +// P0674R1 make_shared() For Arrays // P0758R1 is_nothrow_convertible // P0768R1 Library Support For The Spaceship Comparison Operator <=> // (partially implemented) From e169d41168884d3922ca7840980cf884677285b9 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Tue, 19 Nov 2019 15:09:04 +0100 Subject: [PATCH 03/52] Surround max by parens and checking for __cpp_concepts --- stl/inc/memory | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 93556c65206..ad53fa9bb02 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1254,12 +1254,12 @@ private: } template -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts requires (!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 friend shared_ptr<_Ty> make_shared(_Types&&... _Args); -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts template requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(size_t _Count); @@ -1274,12 +1274,12 @@ private: #endif // _HAS_CXX20 template -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts requires (!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts template requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, size_t _Count); @@ -1598,7 +1598,7 @@ public: size_t _Size; auto _Get_ptr() { - return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + _STD max(sizeof(*this), alignof(_Ty))); + return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); } private: virtual void _Destroy() noexcept override { // destroy managed resource @@ -1606,7 +1606,7 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), _STD max(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -1780,7 +1780,7 @@ public: size_t _Size; auto _Get_ptr() { - return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + _STD max(sizeof(*this), alignof(_Ty))); + return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); } private: ~_Ref_count_unbounded_array_alloc() { @@ -1793,9 +1793,9 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - constexpr size_t _Max_alignment = _STD max(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); + constexpr size_t _Max_alignment = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); using _Storage = _STD aligned_storage_t<_Max_alignment, _Max_alignment>; - constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(*this) / sizeof(_Storage), size_t(1)); + constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(*this) / sizeof(_Storage), size_t(1)); constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); this->~_Ref_count_unbounded_array_alloc(); @@ -1849,7 +1849,7 @@ private: // FUNCTION TEMPLATE make_shared template -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts requires (!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object @@ -1859,12 +1859,12 @@ _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr return _Ret; } -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts template requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared(size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; - using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); new(_Rx) _Refc(_Count); @@ -1876,8 +1876,8 @@ _NODISCARD shared_ptr<_Ty> make_shared(size_t _Count) { // make a shared_ptr to template requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; - using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); new(_Rx) _Refc(_Count, _Val); @@ -1904,7 +1904,7 @@ _NODISCARD shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val) { #endif // _HAS_CXX20 // FUNCTION TEMPLATE allocate_shared template -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts requires (!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object @@ -1922,12 +1922,12 @@ _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) return _Ret; } -#if _HAS_CXX20 +#if _HAS_CXX20 && __cpp_concepts template requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); @@ -1940,8 +1940,8 @@ _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count) { / template requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - using _Storage = _STD aligned_storage_t<_STD max(alignof(_Ty), alignof(_Refc)), _STD max(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = _STD max(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); From dad50ea8f6a2e50f934c8d918ab4e2da9a049a1b Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Tue, 19 Nov 2019 16:26:24 +0100 Subject: [PATCH 04/52] Formatting --- stl/inc/memory | 366 ++++++++++++++++++++++++++++++------------------- 1 file changed, 222 insertions(+), 144 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index ad53fa9bb02..558632e5fdf 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -8,13 +8,13 @@ #define _MEMORY_ #include #if _STL_COMPILER_PREPROCESSOR +#include +#include #include #include #include #include #include -#include -#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -52,7 +52,8 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(_InIt _First, _Diff _Count, const _NoThrowFwdIt _Dest, - false_type) { // copy [_First, _First + _Count) to [_Dest, ...), no special optimization + false_type) { // copy [_First, _First + _Count) to [_Dest, ...), no special + // optimization _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; for (; 0 < _Count; --_Count, (void) ++_First) { _Backout._Emplace_back(*_First); @@ -63,7 +64,8 @@ _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(_InIt _First, _Diff _Count, const template _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(const _InIt _First, const _Diff _Count, const _NoThrowFwdIt _Dest, - true_type) { // copy [_First, _First + _Count) to [_Dest, ...), memmove optimization + true_type) { // copy [_First, _First + _Count) to [_Dest, ...), memmove + // optimization return _Copy_memmove(_First, _First + _Count, _Dest); } @@ -172,7 +174,8 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template pair<_InIt, _NoThrowFwdIt> _Uninitialized_move_n_unchecked1(_InIt _First, _Diff _Count, const _NoThrowFwdIt _Dest, - false_type) { // move [_First, _First + _Count) to [_Dest, ...), no special optimization + false_type) { // move [_First, _First + _Count) to [_Dest, ...), no special + // optimization _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; for (; 0 < _Count; --_Count, (void) ++_First) { _Backout._Emplace_back(_STD move(*_First)); @@ -183,7 +186,8 @@ pair<_InIt, _NoThrowFwdIt> _Uninitialized_move_n_unchecked1(_InIt _First, _Diff template pair<_InIt, _NoThrowFwdIt> _Uninitialized_move_n_unchecked1(_InIt _First, _Diff _Count, _NoThrowFwdIt _Dest, - true_type) { // move [_First, _First + _Count) to [_Dest, ...), memmove optimization + true_type) { // move [_First, _First + _Count) to [_Dest, ...), memmove + // optimization if (0 < _Count) { _Dest = _Copy_memmove(_First, _First + _Count, _Dest); _First += _Count; @@ -212,7 +216,8 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template pair<_InTy*, _NoThrowFwdIt> uninitialized_move_n(_InTy (&_First)[_InSize], const _Diff _Count_raw, - _NoThrowFwdIt _Dest) { // move [_First, _First + _Count) to [_Dest, ...), array input + _NoThrowFwdIt _Dest) { // move [_First, _First + _Count) to + // [_Dest, ...), array input _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { _STL_VERIFY_ARRAY_SIZE(_First, _Count); @@ -236,7 +241,8 @@ pair<_InIt, _OutTy*> uninitialized_move_n(_InIt _First, const _Diff _Count_raw, template pair<_InTy*, _OutTy*> uninitialized_move_n(_InTy (&_First)[_InSize], const _Diff _Count_raw, - _OutTy (&_Dest)[_OutSize]) { // move [_First, _First + _Count) to [_Dest, ...), array input/dest + _OutTy (&_Dest)[_OutSize]) { // move [_First, _First + _Count) to [_Dest, + // ...), array input/dest _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { _STL_VERIFY_ARRAY_SIZE(_First, _Count); @@ -319,7 +325,8 @@ void destroy_at(_Ty* const _Location) { // destroy _Ty at memory address _Locati // FUNCTION TEMPLATE destroy template -void destroy(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last) { // destroy all elements in [_First, _Last) +void destroy(const _NoThrowFwdIt _First, + const _NoThrowFwdIt _Last) { // destroy all elements in [_First, _Last) _Adl_verify_range(_First, _Last); _Destroy_range(_Get_unwrapped(_First), _Get_unwrapped(_Last)); } @@ -419,7 +426,6 @@ _NoThrowFwdIt uninitialized_value_construct_n(_NoThrowFwdIt _First, const _Diff #endif // _HAS_CXX17 - // CLASS TEMPLATE raw_storage_iterator template class _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR raw_storage_iterator { // wrap stores to raw buffer as output iterator @@ -465,7 +471,6 @@ private: _OutIt _Next; }; - #if _HAS_AUTO_PTR_ETC // CLASS TEMPLATE auto_ptr template @@ -499,7 +504,8 @@ public: } template - operator auto_ptr_ref<_Other>() noexcept { // convert to compatible auto_ptr_ref + operator auto_ptr_ref<_Other>() noexcept { // convert to compatible + // auto_ptr_ref _Other* _Cvtptr = _Myptr; // test implicit conversion auto_ptr_ref<_Other> _Ans(_Cvtptr); _Myptr = nullptr; // pass ownership to auto_ptr_ref @@ -557,7 +563,8 @@ public: return _Tmp; } - void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and store new pointer + void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and + // store new pointer if (_Ptr != _Myptr) { delete _Myptr; } @@ -576,9 +583,9 @@ public: }; #endif // _HAS_AUTO_PTR_ETC - // CLASS bad_weak_ptr -class bad_weak_ptr : public exception { // exception type for invalid use of expired weak_ptr object +class bad_weak_ptr : public exception { // exception type for invalid use of + // expired weak_ptr object public: bad_weak_ptr() noexcept {} @@ -596,7 +603,8 @@ public: class __declspec(novtable) _Ref_count_base { // common code for reference counting private: #ifdef _M_CEE_PURE - // permanent workaround to avoid mentioning _purecall in msvcurt.lib, ptrustu.lib, or other support libs + // permanent workaround to avoid mentioning _purecall in msvcurt.lib, + // ptrustu.lib, or other support libs virtual void _Destroy() noexcept { _STD terminate(); } @@ -621,7 +629,8 @@ public: virtual ~_Ref_count_base() noexcept {} // TRANSITION, should be non-virtual - bool _Incref_nz() noexcept { // increment use count if not zero, return true if successful + bool _Incref_nz() noexcept { // increment use count if not zero, return true + // if successful auto& _Volatile_uses = reinterpret_cast(_Uses); long _Count = _ISO_VOLATILE_LOAD32(_Volatile_uses); @@ -669,7 +678,8 @@ public: // CLASS TEMPLATE _Ref_count template -class _Ref_count : public _Ref_count_base { // handle reference counting for pointer without deleter +class _Ref_count : public _Ref_count_base { // handle reference counting for + // pointer without deleter public: explicit _Ref_count(_Ty* _Px) : _Ref_count_base(), _Ptr(_Px) {} @@ -687,7 +697,8 @@ private: // CLASS TEMPLATE _Ref_count_resource template -class _Ref_count_resource : public _Ref_count_base { // handle reference counting for object with deleter +class _Ref_count_resource : public _Ref_count_base { // handle reference counting for object with + // deleter public: _Ref_count_resource(_Resource _Px, _Dx _Dt) : _Ref_count_base(), _Mypair(_One_then_variadic_args_t(), _STD move(_Dt), _Px) {} @@ -1045,7 +1056,8 @@ public: enable_if_t, _Can_call_function_object<_Dx&, _Ux*&>, _SP_convertible<_Ux, _Ty>>, int> = 0> - shared_ptr(_Ux* _Px, _Dx _Dt, _Alloc _Ax) { // construct with _Px, deleter, allocator + shared_ptr(_Ux* _Px, _Dx _Dt, + _Alloc _Ax) { // construct with _Px, deleter, allocator _Setpda(_Px, _STD move(_Dt), _Ax); } @@ -1057,7 +1069,8 @@ public: template , _Can_call_function_object<_Dx&, nullptr_t&>>, int> = 0> - shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax) { // construct with nullptr, deleter, allocator + shared_ptr(nullptr_t, _Dx _Dt, + _Alloc _Ax) { // construct with nullptr, deleter, allocator _Setpda(nullptr, _STD move(_Dt), _Ax); } @@ -1073,7 +1086,8 @@ public: this->_Alias_move_construct_from(_STD move(_Right), _Px); } - shared_ptr(const shared_ptr& _Other) noexcept { // construct shared_ptr object that owns same resource as _Other + shared_ptr(const shared_ptr& _Other) noexcept { // construct shared_ptr object that + // owns same resource as _Other this->_Copy_construct_from(_Other); } @@ -1083,12 +1097,14 @@ public: this->_Copy_construct_from(_Other); } - shared_ptr(shared_ptr&& _Right) noexcept { // construct shared_ptr object that takes resource from _Right + shared_ptr(shared_ptr&& _Right) noexcept { // construct shared_ptr object that + // takes resource from _Right this->_Move_construct_from(_STD move(_Right)); } template ::value, int> = 0> - shared_ptr(shared_ptr<_Ty2>&& _Right) noexcept { // construct shared_ptr object that takes resource from _Right + shared_ptr(shared_ptr<_Ty2>&& _Right) noexcept { // construct shared_ptr object that + // takes resource from _Right this->_Move_construct_from(_STD move(_Right)); } @@ -1101,7 +1117,8 @@ public: #if _HAS_AUTO_PTR_ETC template , int> = 0> - shared_ptr(auto_ptr<_Ty2>&& _Other) { // construct shared_ptr object that owns *_Other.get() + shared_ptr(auto_ptr<_Ty2>&& _Other) { // construct shared_ptr object that owns + // *_Other.get() _Ty2* _Px = _Other.get(); _Set_ptr_rep_and_enable_shared(_Px, new _Ref_count<_Ty2>(_Px)); _Other.release(); @@ -1181,12 +1198,14 @@ public: } template - void reset(_Ux* _Px, _Dx _Dt) { // release, take ownership of _Px, with deleter _Dt + void reset(_Ux* _Px, + _Dx _Dt) { // release, take ownership of _Px, with deleter _Dt shared_ptr(_Px, _Dt).swap(*this); } template - void reset(_Ux* _Px, _Dx _Dt, _Alloc _Ax) { // release, take ownership of _Px, with deleter _Dt, allocator _Ax + void reset(_Ux* _Px, _Dx _Dt, _Alloc _Ax) { // release, take ownership of _Px, + // with deleter _Dt, allocator _Ax shared_ptr(_Px, _Dt, _Ax).swap(*this); } @@ -1203,7 +1222,8 @@ public: } template , int> = 0> - _NODISCARD _Elem& operator[](ptrdiff_t _Idx) const noexcept /* strengthened */ { + _NODISCARD _Elem& operator[](ptrdiff_t _Idx) const noexcept + /* strengthened */ { return get()[_Idx]; } @@ -1232,7 +1252,8 @@ private: #endif // !_HAS_IF_CONSTEXPR template - void _Setpd(const _UxptrOrNullptr _Px, _Dx _Dt) { // take ownership of _Px, deleter _Dt + void _Setpd(const _UxptrOrNullptr _Px, + _Dx _Dt) { // take ownership of _Px, deleter _Dt _Temporary_owner_del<_UxptrOrNullptr, _Dx> _Owner(_Px, _Dt); _Set_ptr_rep_and_enable_shared( _Owner._Ptr, new _Ref_count_resource<_UxptrOrNullptr, _Dx>(_Owner._Ptr, _STD move(_Dt))); @@ -1240,7 +1261,8 @@ private: } template - void _Setpda(const _UxptrOrNullptr _Px, _Dx _Dt, _Alloc _Ax) { // take ownership of _Px, deleter _Dt, allocator _Ax + void _Setpda(const _UxptrOrNullptr _Px, _Dx _Dt, + _Alloc _Ax) { // take ownership of _Px, deleter _Dt, allocator _Ax using _Alref_alloc = _Rebind_alloc_t<_Alloc, _Ref_count_resource_alloc<_UxptrOrNullptr, _Dx, _Alloc>>; _Temporary_owner_del<_UxptrOrNullptr, _Dx> _Owner(_Px, _Dt); @@ -1255,46 +1277,51 @@ private: template #if _HAS_CXX20 && __cpp_concepts - requires (!_STD is_array_v<_Ty>) + requires(!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 - friend shared_ptr<_Ty> make_shared(_Types&&... _Args); + friend shared_ptr<_Ty> make_shared(_Types&&... _Args); #if _HAS_CXX20 && __cpp_concepts - template requires _STD is_unbounded_array_v<_Ty> - friend shared_ptr<_Ty> make_shared(size_t _Count); + template + requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(size_t _Count); - template requires _STD is_unbounded_array_v<_Ty> - friend shared_ptr<_Ty> make_shared(size_t _Count, const _STD remove_extent_t<_Ty>& _Val); + template + requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared( + size_t _Count, const _STD remove_extent_t<_Ty>& _Val); - template requires _STD is_bounded_array_v<_Ty> - friend shared_ptr<_Ty> make_shared(); + template + requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(); - template requires _STD is_bounded_array_v<_Ty> - friend shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val); + template + requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val); #endif // _HAS_CXX20 template #if _HAS_CXX20 && __cpp_concepts - requires (!_STD is_array_v<_Ty>) + requires(!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 - friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); #if _HAS_CXX20 && __cpp_concepts - template requires _STD is_unbounded_array_v<_Ty> - friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, size_t _Count); + template + requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al_arg, size_t _Count); - template requires _STD is_unbounded_array_v<_Ty> - friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val); + template + requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val); - template requires _STD is_bounded_array_v<_Ty> - friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg); + template + requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg); - template requires _STD is_bounded_array_v<_Ty> - friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, const _STD remove_extent_t<_Ty>& _Val); + template + requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al_arg, const _STD remove_extent_t<_Ty>& _Val); #endif // _HAS_CXX20 template - void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px + void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, + _Ref_count_base* const _Rx) noexcept { // take ownership of _Px this->_Ptr = _Px; this->_Rep = _Rx; #if _HAS_IF_CONSTEXPR @@ -1310,7 +1337,8 @@ private: #endif // _HAS_IF_CONSTEXPR } - void _Set_ptr_rep_and_enable_shared(nullptr_t, _Ref_count_base* const _Rx) noexcept { // take ownership of nullptr + void _Set_ptr_rep_and_enable_shared(nullptr_t, + _Ref_count_base* const _Rx) noexcept { // take ownership of nullptr this->_Ptr = nullptr; this->_Rep = _Rx; } @@ -1427,42 +1455,48 @@ void swap(shared_ptr<_Ty>& _Left, shared_ptr<_Ty>& _Right) noexcept { template _NODISCARD shared_ptr<_Ty1> static_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // static_cast for shared_ptr that properly respects the reference count control block + // static_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = static_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_Other, _Ptr); } template _NODISCARD shared_ptr<_Ty1> static_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // static_cast for shared_ptr that properly respects the reference count control block + // static_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = static_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_STD move(_Other), _Ptr); } template _NODISCARD shared_ptr<_Ty1> const_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // const_cast for shared_ptr that properly respects the reference count control block + // const_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = const_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_Other, _Ptr); } template _NODISCARD shared_ptr<_Ty1> const_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // const_cast for shared_ptr that properly respects the reference count control block + // const_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = const_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_STD move(_Other), _Ptr); } template _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // reinterpret_cast for shared_ptr that properly respects the reference count control block + // reinterpret_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = reinterpret_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_Other, _Ptr); } template _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // reinterpret_cast for shared_ptr that properly respects the reference count control block + // reinterpret_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = reinterpret_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_STD move(_Other), _Ptr); } @@ -1470,7 +1504,8 @@ _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(shared_ptr<_Ty2>&& _Other) #ifdef _CPPRTTI template _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // dynamic_cast for shared_ptr that properly respects the reference count control block + // dynamic_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = dynamic_cast::element_type*>(_Other.get()); if (_Ptr) { @@ -1482,7 +1517,8 @@ _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>& _Other) template _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // dynamic_cast for shared_ptr that properly respects the reference count control block + // dynamic_cast for shared_ptr that properly respects the reference count + // control block const auto _Ptr = dynamic_cast::element_type*>(_Other.get()); if (_Ptr) { @@ -1515,7 +1551,8 @@ _Dx* get_deleter(const shared_ptr<_Ty>&) noexcept = delete; // requires static R // CLASS TEMPLATE _Ref_count_obj2 template -class _Ref_count_obj2 : public _Ref_count_base { // handle reference counting for object in control block, no allocator +class _Ref_count_obj2 : public _Ref_count_base { // handle reference counting for object in + // control block, no allocator public: template explicit _Ref_count_obj2(_Types&&... _Args) : _Ref_count_base() { @@ -1576,13 +1613,15 @@ void _Reverse_destroy_md_n(_Ty* _Arr, size_t _Size) { // CLASS TEMPLATE _Ref_count_unbounded_array template -class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array in control block, no allocator +class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array + // in control block, no allocator public: explicit _Ref_count_unbounded_array(size_t _Count) : _Ref_count_base(), _Size(_Count) { _Uninitialized_value_construct_md_n(_Get_ptr(), _Size); } - explicit _Ref_count_unbounded_array(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) : _Ref_count_base(), _Size(_Count) { + explicit _Ref_count_unbounded_array(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) + : _Ref_count_base(), _Size(_Count) { if constexpr (_STD rank_v<_Ty> > 1) { for (size_t _It = 0; _It < _Size; ++_It) _Uninitialized_copy_md(_Val, _Get_ptr()[_It]); @@ -1598,15 +1637,18 @@ public: size_t _Size; auto _Get_ptr() { - return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); + return reinterpret_cast<_STD remove_extent_t<_Ty>*>( + reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); } + private: virtual void _Destroy() noexcept override { // destroy managed resource _Reverse_destroy_md_n(_Get_ptr(), _Size); } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), + (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -1614,11 +1656,10 @@ private: // CLASS TEMPLATE _Ref_count_bounded_array template -class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in control block, no allocator +class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in + // control block, no allocator public: - explicit _Ref_count_bounded_array() : _Ref_count_base(), _Storage() { - - } + explicit _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} explicit _Ref_count_bounded_array(const _STD remove_extent_t<_Ty>& _Val) : _Ref_count_base() { if constexpr (_STD rank_v<_Ty> > 1) { @@ -1766,7 +1807,8 @@ public: _Uninitialized_value_construct_md_n_al(_Get_ptr(), _Size, _Alty); } - explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) + explicit _Ref_count_unbounded_array_alloc( + const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); if constexpr (_STD rank_v<_Ty> > 1) { @@ -1780,8 +1822,10 @@ public: size_t _Size; auto _Get_ptr() { - return reinterpret_cast<_STD remove_extent_t<_Ty>*>(reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); + return reinterpret_cast<_STD remove_extent_t<_Ty>*>( + reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); } + private: ~_Ref_count_unbounded_array_alloc() { // nothing to do; _Storage._Value already destroyed by _Destroy() @@ -1793,13 +1837,16 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - constexpr size_t _Max_alignment = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); - using _Storage = _STD aligned_storage_t<_Max_alignment, _Max_alignment>; + constexpr size_t _Max_alignment = + (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); + using _Storage = _STD aligned_storage_t<_Max_alignment, _Max_alignment>; constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(*this) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + constexpr double _Ty_size_div_by_storage_size = + static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); this->~_Ref_count_unbounded_array_alloc(); - allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), static_cast(ceil(_Size * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size); + allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), + static_cast(ceil(_Size * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size); } }; @@ -1808,8 +1855,7 @@ template class __declspec(empty_bases) _Ref_count_bounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { // handle reference counting for object in control block, allocator public: - explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) - : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { + explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); _Uninitialized_value_construct_md_n_al(_Storage._Value, _STD extent_v<_Ty>, _Alty); } @@ -1850,9 +1896,9 @@ private: // FUNCTION TEMPLATE make_shared template #if _HAS_CXX20 && __cpp_concepts - requires (!_STD is_array_v<_Ty>) +requires(!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 -_NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object + _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_STD addressof(_Rx->_Storage._Value), _Rx); @@ -1860,42 +1906,51 @@ _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr } #if _HAS_CXX20 && __cpp_concepts -template requires _STD is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared(size_t _Count) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array<_Ty>; - using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; +template +requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( + size_t _Count) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array<_Ty>; + using _Storage = + _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); - const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); - new(_Rx) _Refc(_Count); + constexpr double _Ty_size_div_by_storage_size = + static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + const auto _Rx = reinterpret_cast<_Refc*>( + new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); + new (_Rx) _Refc(_Count); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } -template requires _STD is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array<_Ty>; - using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; +template +requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared(size_t _Count, + const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array<_Ty>; + using _Storage = + _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); - const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); - new(_Rx) _Refc(_Count, _Val); + constexpr double _Ty_size_div_by_storage_size = + static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + const auto _Rx = reinterpret_cast<_Refc*>( + new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); + new (_Rx) _Refc(_Count, _Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } -template requires _STD is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array +template +requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); return _Ret; } -template requires _STD is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array +template +requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( + const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); @@ -1905,11 +1960,13 @@ _NODISCARD shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val) { // FUNCTION TEMPLATE allocate_shared template #if _HAS_CXX20 && __cpp_concepts - requires (!_STD is_array_v<_Ty>) +requires(!_STD is_array_v<_Ty>) #endif // _HAS_CXX20 -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object - // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether - // allocator::construct sees T or const T when _Ty is const qualified) + _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, + _Types&&... _Args) { // make a shared_ptr to non-array object + // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 + // (which controls whether allocator::construct sees T or const T when _Ty is + // const qualified) using _Refoa = _Ref_count_obj_alloc2, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refoa>; _Alblock _Rebound(_Al); @@ -1923,53 +1980,63 @@ _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, _Types&&... _Args) } #if _HAS_CXX20 && __cpp_concepts -template requires _STD is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; +template +requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, + size_t _Count) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; + using _Storage = + _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + constexpr double _Ty_size_div_by_storage_size = + static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); - new(_Rx) _Refc(_Al, _Count); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate( + static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); + new (_Rx) _Refc(_Al, _Count); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } -template requires _STD is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; +template +requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, + const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array + using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; + using _Storage = + _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + constexpr double _Ty_size_div_by_storage_size = + static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); - new(_Rx) _Refc(_Al, _Count, _Val); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate( + static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); + new (_Rx) _Refc(_Al, _Count, _Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } -template requires _STD is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al) { // make a shared_ptr to a bounded array +template +requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); const auto _Rx = _Rebound.allocate(1); - new(_Rx) _Refc(_Al); + new (_Rx) _Refc(_Al); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); return _Ret; } -template requires _STD is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array +template +requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, + const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); const auto _Rx = _Rebound.allocate(1); - new(_Rx) _Refc(_Al, _Val); + new (_Rx) _Refc(_Al, _Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); return _Ret; @@ -1982,17 +2049,20 @@ class weak_ptr : public _Ptr_base<_Ty> { // class for pointer to reference count public: constexpr weak_ptr() noexcept {} // construct empty weak_ptr object - weak_ptr(const weak_ptr& _Other) noexcept { // construct weak_ptr object for resource pointed to by _Other + weak_ptr(const weak_ptr& _Other) noexcept { // construct weak_ptr object for + // resource pointed to by _Other this->_Weakly_construct_from(_Other); } template ::value, int> = 0> - weak_ptr(const shared_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for resource owned by _Other + weak_ptr(const shared_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object + // for resource owned by _Other this->_Weakly_construct_from(_Other); } template ::value, int> = 0> - weak_ptr(const weak_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for resource pointed to by _Other + weak_ptr(const weak_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for + // resource pointed to by _Other this->_Weakly_construct_from(_Other.lock()); } @@ -2069,7 +2139,8 @@ void swap(weak_ptr<_Ty>& _Left, weak_ptr<_Ty>& _Right) noexcept { // CLASS TEMPLATE enable_shared_from_this template -class enable_shared_from_this { // provide member functions that create shared_ptr to this +class enable_shared_from_this { // provide member functions that create + // shared_ptr to this public: using _Esft_type = enable_shared_from_this; @@ -2114,7 +2185,6 @@ private: mutable weak_ptr<_Ty> _Wptr; }; - // CLASS TEMPLATE unique_ptr AND HELPERS // STRUCT TEMPLATE default_delete @@ -2125,21 +2195,24 @@ struct default_delete { // default deleter for unique_ptr template , int> = 0> default_delete(const default_delete<_Ty2>&) noexcept {} - void operator()(_Ty* _Ptr) const noexcept /* strengthened */ { // delete a pointer + void operator()(_Ty* _Ptr) const noexcept + /* strengthened */ { // delete a pointer static_assert(0 < sizeof(_Ty), "can't delete an incomplete type"); delete _Ptr; } }; template -struct default_delete<_Ty[]> { // default deleter for unique_ptr to array of unknown size +struct default_delete<_Ty[]> { // default deleter for unique_ptr to array of + // unknown size constexpr default_delete() noexcept = default; template , int> = 0> default_delete(const default_delete<_Uty[]>&) noexcept {} template , int> = 0> - void operator()(_Uty* _Ptr) const noexcept /* strengthened */ { // delete a pointer + void operator()(_Uty* _Ptr) const noexcept + /* strengthened */ { // delete a pointer static_assert(0 < sizeof(_Uty), "can't delete an incomplete type"); delete[] _Ptr; } @@ -2152,7 +2225,8 @@ struct _Get_deleter_pointer_type { // provide fallback }; template -struct _Get_deleter_pointer_type<_Ty, _Dx_noref, void_t> { // get _Dx_noref::pointer +struct _Get_deleter_pointer_type<_Ty, _Dx_noref, + void_t> { // get _Dx_noref::pointer using type = typename _Dx_noref::pointer; }; @@ -2254,7 +2328,8 @@ public: return _Mypair._Get_first(); } - _NODISCARD add_lvalue_reference_t<_Ty> operator*() const noexcept /* strengthened */ { + _NODISCARD add_lvalue_reference_t<_Ty> operator*() const noexcept + /* strengthened */ { return *_Mypair._Myval2; } @@ -2303,12 +2378,13 @@ public: constexpr unique_ptr() noexcept : _Mypair(_Zero_then_variadic_args_t()) {} template > - using _Enable_ctor_reset = - enable_if_t // - || _Is_nullptr::value // - || (is_same_v // - && is_pointer_v<_Uty> // - && is_convertible_v (*)[], element_type (*)[]>)>; // TRANSITION, GH-248 + using _Enable_ctor_reset = enable_if_t // + || _Is_nullptr::value // + || (is_same_v // + && is_pointer_v<_Uty> // + && is_convertible_v (*)[], + element_type (*)[]>)>; // TRANSITION, + // GH-248 template = 0, class = _Enable_ctor_reset<_Uty>> explicit unique_ptr(_Uty _Ptr) noexcept : _Mypair(_Zero_then_variadic_args_t(), _Ptr) {} @@ -2347,9 +2423,9 @@ public: template ::pointer, class _UP_element_type = typename unique_ptr<_Uty, _Ex>::element_type> - using _Enable_conversion = enable_if_t< - conjunction_v, is_same, is_same<_UP_pointer, _UP_element_type*>, - is_convertible<_UP_element_type (*)[], element_type (*)[]>, _More>>; // TRANSITION, GH-248 + using _Enable_conversion = enable_if_t, is_same, + is_same<_UP_pointer, _UP_element_type*>, is_convertible<_UP_element_type (*)[], element_type (*)[]>, + _More>>; // TRANSITION, GH-248 template _Mypair; }; - // FUNCTION TEMPLATE make_unique template , int> = 0> _NODISCARD unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr @@ -2684,7 +2759,8 @@ inline void* align(size_t _Bound, size_t _Size, void*& _Ptr, size_t& _Space) noe #if _HAS_CXX20 && 0 template -_NODISCARD constexpr _Ty* assume_aligned(_Ty* _Ptr) noexcept /* strengthened */ { +_NODISCARD constexpr _Ty* assume_aligned(_Ty* _Ptr) noexcept +/* strengthened */ { // this enforces the requirement that _N0 be a power of two __builtin_assume_aligned(_Ptr, _N0); @@ -2699,7 +2775,8 @@ _CRTIMP2_PURE void __cdecl _Unlock_shared_ptr_spin_lock(); _END_EXTERN_C // WRAP SPIN-LOCK -struct _Shared_ptr_spin_lock { // class to manage a spin lock for shared_ptr atomic operations +struct _Shared_ptr_spin_lock { // class to manage a spin lock for shared_ptr + // atomic operations _Shared_ptr_spin_lock() { // lock the spin lock _Lock_shared_ptr_spin_lock(); } @@ -2736,7 +2813,8 @@ void atomic_store_explicit(shared_ptr<_Ty>* _Ptr, shared_ptr<_Ty> _Other, memory } template -void atomic_store(shared_ptr<_Ty>* _Ptr, shared_ptr<_Ty> _Other) { // store _Other to *_Ptr atomically +void atomic_store(shared_ptr<_Ty>* _Ptr, + shared_ptr<_Ty> _Other) { // store _Other to *_Ptr atomically _STD atomic_store_explicit(_Ptr, _STD move(_Other), memory_order_seq_cst); } From 07aaa502fb05f07707009f00a7c731ccd82ec084 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 21 Nov 2019 17:41:28 +0100 Subject: [PATCH 05/52] Lots of Fixes --- stl/inc/memory | 622 +++++++++++++++++++++++++------------------------ 1 file changed, 314 insertions(+), 308 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 558632e5fdf..35af17f7279 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -8,12 +8,11 @@ #define _MEMORY_ #include #if _STL_COMPILER_PREPROCESSOR -#include -#include #include #include #include #include +#include #include #pragma pack(push, _CRT_PACKING) @@ -52,8 +51,7 @@ _NoThrowFwdIt uninitialized_copy_n(const _InIt _First, const _Diff _Count_raw, _ #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(_InIt _First, _Diff _Count, const _NoThrowFwdIt _Dest, - false_type) { // copy [_First, _First + _Count) to [_Dest, ...), no special - // optimization + false_type) { // copy [_First, _First + _Count) to [_Dest, ...), no special optimization _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; for (; 0 < _Count; --_Count, (void) ++_First) { _Backout._Emplace_back(*_First); @@ -64,8 +62,7 @@ _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(_InIt _First, _Diff _Count, const template _NoThrowFwdIt _Uninitialized_copy_n_unchecked2(const _InIt _First, const _Diff _Count, const _NoThrowFwdIt _Dest, - true_type) { // copy [_First, _First + _Count) to [_Dest, ...), memmove - // optimization + true_type) { // copy [_First, _First + _Count) to [_Dest, ...), memmove optimization return _Copy_memmove(_First, _First + _Count, _Dest); } @@ -174,8 +171,7 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count #else // ^^^ _HAS_IF_CONSTEXPR / !_HAS_IF_CONSTEXPR vvv template pair<_InIt, _NoThrowFwdIt> _Uninitialized_move_n_unchecked1(_InIt _First, _Diff _Count, const _NoThrowFwdIt _Dest, - false_type) { // move [_First, _First + _Count) to [_Dest, ...), no special - // optimization + false_type) { // move [_First, _First + _Count) to [_Dest, ...), no special optimization _Uninitialized_backout<_NoThrowFwdIt> _Backout{_Dest}; for (; 0 < _Count; --_Count, (void) ++_First) { _Backout._Emplace_back(_STD move(*_First)); @@ -186,8 +182,7 @@ pair<_InIt, _NoThrowFwdIt> _Uninitialized_move_n_unchecked1(_InIt _First, _Diff template pair<_InIt, _NoThrowFwdIt> _Uninitialized_move_n_unchecked1(_InIt _First, _Diff _Count, _NoThrowFwdIt _Dest, - true_type) { // move [_First, _First + _Count) to [_Dest, ...), memmove - // optimization + true_type) { // move [_First, _First + _Count) to [_Dest, ...), memmove optimization if (0 < _Count) { _Dest = _Copy_memmove(_First, _First + _Count, _Dest); _First += _Count; @@ -216,8 +211,7 @@ pair<_InIt, _NoThrowFwdIt> uninitialized_move_n(_InIt _First, const _Diff _Count #if _ITERATOR_DEBUG_ARRAY_OVERLOADS template pair<_InTy*, _NoThrowFwdIt> uninitialized_move_n(_InTy (&_First)[_InSize], const _Diff _Count_raw, - _NoThrowFwdIt _Dest) { // move [_First, _First + _Count) to - // [_Dest, ...), array input + _NoThrowFwdIt _Dest) { // move [_First, _First + _Count) to [_Dest, ...), array input _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { _STL_VERIFY_ARRAY_SIZE(_First, _Count); @@ -241,8 +235,7 @@ pair<_InIt, _OutTy*> uninitialized_move_n(_InIt _First, const _Diff _Count_raw, template pair<_InTy*, _OutTy*> uninitialized_move_n(_InTy (&_First)[_InSize], const _Diff _Count_raw, - _OutTy (&_Dest)[_OutSize]) { // move [_First, _First + _Count) to [_Dest, - // ...), array input/dest + _OutTy (&_Dest)[_OutSize]) { // move [_First, _First + _Count) to [_Dest, ...), array input/dest _Algorithm_int_t<_Diff> _Count = _Count_raw; if (0 < _Count) { _STL_VERIFY_ARRAY_SIZE(_First, _Count); @@ -325,8 +318,7 @@ void destroy_at(_Ty* const _Location) { // destroy _Ty at memory address _Locati // FUNCTION TEMPLATE destroy template -void destroy(const _NoThrowFwdIt _First, - const _NoThrowFwdIt _Last) { // destroy all elements in [_First, _Last) +void destroy(const _NoThrowFwdIt _First, const _NoThrowFwdIt _Last) { // destroy all elements in [_First, _Last) _Adl_verify_range(_First, _Last); _Destroy_range(_Get_unwrapped(_First), _Get_unwrapped(_Last)); } @@ -426,6 +418,7 @@ _NoThrowFwdIt uninitialized_value_construct_n(_NoThrowFwdIt _First, const _Diff #endif // _HAS_CXX17 + // CLASS TEMPLATE raw_storage_iterator template class _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR raw_storage_iterator { // wrap stores to raw buffer as output iterator @@ -471,6 +464,7 @@ private: _OutIt _Next; }; + #if _HAS_AUTO_PTR_ETC // CLASS TEMPLATE auto_ptr template @@ -504,8 +498,7 @@ public: } template - operator auto_ptr_ref<_Other>() noexcept { // convert to compatible - // auto_ptr_ref + operator auto_ptr_ref<_Other>() noexcept { // convert to compatible auto_ptr_ref _Other* _Cvtptr = _Myptr; // test implicit conversion auto_ptr_ref<_Other> _Ans(_Cvtptr); _Myptr = nullptr; // pass ownership to auto_ptr_ref @@ -563,8 +556,7 @@ public: return _Tmp; } - void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and - // store new pointer + void reset(_Ty* _Ptr = nullptr) noexcept { // destroy designated object and store new pointer if (_Ptr != _Myptr) { delete _Myptr; } @@ -583,9 +575,9 @@ public: }; #endif // _HAS_AUTO_PTR_ETC + // CLASS bad_weak_ptr -class bad_weak_ptr : public exception { // exception type for invalid use of - // expired weak_ptr object +class bad_weak_ptr : public exception { // exception type for invalid use of expired weak_ptr object public: bad_weak_ptr() noexcept {} @@ -603,8 +595,7 @@ public: class __declspec(novtable) _Ref_count_base { // common code for reference counting private: #ifdef _M_CEE_PURE - // permanent workaround to avoid mentioning _purecall in msvcurt.lib, - // ptrustu.lib, or other support libs + // permanent workaround to avoid mentioning _purecall in msvcurt.lib, ptrustu.lib, or other support libs virtual void _Destroy() noexcept { _STD terminate(); } @@ -629,8 +620,7 @@ public: virtual ~_Ref_count_base() noexcept {} // TRANSITION, should be non-virtual - bool _Incref_nz() noexcept { // increment use count if not zero, return true - // if successful + bool _Incref_nz() noexcept { // increment use count if not zero, return true if successful auto& _Volatile_uses = reinterpret_cast(_Uses); long _Count = _ISO_VOLATILE_LOAD32(_Volatile_uses); @@ -678,8 +668,7 @@ public: // CLASS TEMPLATE _Ref_count template -class _Ref_count : public _Ref_count_base { // handle reference counting for - // pointer without deleter +class _Ref_count : public _Ref_count_base { // handle reference counting for pointer without deleter public: explicit _Ref_count(_Ty* _Px) : _Ref_count_base(), _Ptr(_Px) {} @@ -697,8 +686,7 @@ private: // CLASS TEMPLATE _Ref_count_resource template -class _Ref_count_resource : public _Ref_count_base { // handle reference counting for object with - // deleter +class _Ref_count_resource : public _Ref_count_base { // handle reference counting for object with deleter public: _Ref_count_resource(_Resource _Px, _Dx _Dt) : _Ref_count_base(), _Mypair(_One_then_variadic_args_t(), _STD move(_Dt), _Px) {} @@ -1056,8 +1044,7 @@ public: enable_if_t, _Can_call_function_object<_Dx&, _Ux*&>, _SP_convertible<_Ux, _Ty>>, int> = 0> - shared_ptr(_Ux* _Px, _Dx _Dt, - _Alloc _Ax) { // construct with _Px, deleter, allocator + shared_ptr(_Ux* _Px, _Dx _Dt, _Alloc _Ax) { // construct with _Px, deleter, allocator _Setpda(_Px, _STD move(_Dt), _Ax); } @@ -1069,8 +1056,7 @@ public: template , _Can_call_function_object<_Dx&, nullptr_t&>>, int> = 0> - shared_ptr(nullptr_t, _Dx _Dt, - _Alloc _Ax) { // construct with nullptr, deleter, allocator + shared_ptr(nullptr_t, _Dx _Dt, _Alloc _Ax) { // construct with nullptr, deleter, allocator _Setpda(nullptr, _STD move(_Dt), _Ax); } @@ -1086,8 +1072,7 @@ public: this->_Alias_move_construct_from(_STD move(_Right), _Px); } - shared_ptr(const shared_ptr& _Other) noexcept { // construct shared_ptr object that - // owns same resource as _Other + shared_ptr(const shared_ptr& _Other) noexcept { // construct shared_ptr object that owns same resource as _Other this->_Copy_construct_from(_Other); } @@ -1097,14 +1082,12 @@ public: this->_Copy_construct_from(_Other); } - shared_ptr(shared_ptr&& _Right) noexcept { // construct shared_ptr object that - // takes resource from _Right + shared_ptr(shared_ptr&& _Right) noexcept { // construct shared_ptr object that takes resource from _Right this->_Move_construct_from(_STD move(_Right)); } template ::value, int> = 0> - shared_ptr(shared_ptr<_Ty2>&& _Right) noexcept { // construct shared_ptr object that - // takes resource from _Right + shared_ptr(shared_ptr<_Ty2>&& _Right) noexcept { // construct shared_ptr object that takes resource from _Right this->_Move_construct_from(_STD move(_Right)); } @@ -1117,8 +1100,7 @@ public: #if _HAS_AUTO_PTR_ETC template , int> = 0> - shared_ptr(auto_ptr<_Ty2>&& _Other) { // construct shared_ptr object that owns - // *_Other.get() + shared_ptr(auto_ptr<_Ty2>&& _Other) { // construct shared_ptr object that owns *_Other.get() _Ty2* _Px = _Other.get(); _Set_ptr_rep_and_enable_shared(_Px, new _Ref_count<_Ty2>(_Px)); _Other.release(); @@ -1198,14 +1180,12 @@ public: } template - void reset(_Ux* _Px, - _Dx _Dt) { // release, take ownership of _Px, with deleter _Dt + void reset(_Ux* _Px, _Dx _Dt) { // release, take ownership of _Px, with deleter _Dt shared_ptr(_Px, _Dt).swap(*this); } template - void reset(_Ux* _Px, _Dx _Dt, _Alloc _Ax) { // release, take ownership of _Px, - // with deleter _Dt, allocator _Ax + void reset(_Ux* _Px, _Dx _Dt, _Alloc _Ax) { // release, take ownership of _Px, with deleter _Dt, allocator _Ax shared_ptr(_Px, _Dt, _Ax).swap(*this); } @@ -1222,8 +1202,7 @@ public: } template , int> = 0> - _NODISCARD _Elem& operator[](ptrdiff_t _Idx) const noexcept - /* strengthened */ { + _NODISCARD _Elem& operator[](ptrdiff_t _Idx) const noexcept /* strengthened */ { return get()[_Idx]; } @@ -1252,8 +1231,7 @@ private: #endif // !_HAS_IF_CONSTEXPR template - void _Setpd(const _UxptrOrNullptr _Px, - _Dx _Dt) { // take ownership of _Px, deleter _Dt + void _Setpd(const _UxptrOrNullptr _Px, _Dx _Dt) { // take ownership of _Px, deleter _Dt _Temporary_owner_del<_UxptrOrNullptr, _Dx> _Owner(_Px, _Dt); _Set_ptr_rep_and_enable_shared( _Owner._Ptr, new _Ref_count_resource<_UxptrOrNullptr, _Dx>(_Owner._Ptr, _STD move(_Dt))); @@ -1261,8 +1239,7 @@ private: } template - void _Setpda(const _UxptrOrNullptr _Px, _Dx _Dt, - _Alloc _Ax) { // take ownership of _Px, deleter _Dt, allocator _Ax + void _Setpda(const _UxptrOrNullptr _Px, _Dx _Dt, _Alloc _Ax) { // take ownership of _Px, deleter _Dt, allocator _Ax using _Alref_alloc = _Rebind_alloc_t<_Alloc, _Ref_count_resource_alloc<_UxptrOrNullptr, _Dx, _Alloc>>; _Temporary_owner_del<_UxptrOrNullptr, _Dx> _Owner(_Px, _Dt); @@ -1275,53 +1252,51 @@ private: _Owner._Call_deleter = false; } - template -#if _HAS_CXX20 && __cpp_concepts - requires(!_STD is_array_v<_Ty>) -#endif // _HAS_CXX20 - friend shared_ptr<_Ty> make_shared(_Types&&... _Args); + template +#if _HAS_CXX20 && defined(__cpp_concepts) + requires(!is_array_v<_Ty0>) +#endif // _HAS_CXX20 && defined(__cpp_concepts) + friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); -#if _HAS_CXX20 && __cpp_concepts - template - requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(size_t _Count); +#if _HAS_CXX20 && defined(__cpp_concepts) + template + requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(size_t _Count); - template - requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared( - size_t _Count, const _STD remove_extent_t<_Ty>& _Val); + template + requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared( + size_t _Count, const remove_extent_t<_Ty0>& _Val); - template - requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(); + template + requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(); - template - requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> make_shared(const _STD remove_extent_t<_Ty>& _Val); -#endif // _HAS_CXX20 + template + requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); +#endif // _HAS_CXX20 && defined(__cpp_concepts) - template -#if _HAS_CXX20 && __cpp_concepts - requires(!_STD is_array_v<_Ty>) -#endif // _HAS_CXX20 - friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + template +#if _HAS_CXX20 && defined(__cpp_concepts) + requires(!is_array_v<_Ty0>) +#endif // _HAS_CXX20 && defined(__cpp_concepts) + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); -#if _HAS_CXX20 && __cpp_concepts - template - requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared( - const _Alloc& _Al_arg, size_t _Count); +#if _HAS_CXX20 && defined(__cpp_concepts) + template + requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, size_t _Count); - template - requires _STD is_unbounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared( - const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val); + template + requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared( + const _Alloc& _Al_arg, size_t _Count, const remove_extent_t<_Ty0>& _Val); - template - requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared(const _Alloc& _Al_arg); + template + requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg); - template - requires _STD is_bounded_array_v<_Ty> friend shared_ptr<_Ty> allocate_shared( - const _Alloc& _Al_arg, const _STD remove_extent_t<_Ty>& _Val); -#endif // _HAS_CXX20 + template + requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared( + const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); +#endif // _HAS_CXX20 && defined(__cpp_concepts) template - void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, - _Ref_count_base* const _Rx) noexcept { // take ownership of _Px + void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px this->_Ptr = _Px; this->_Rep = _Rx; #if _HAS_IF_CONSTEXPR @@ -1337,8 +1312,7 @@ private: #endif // _HAS_IF_CONSTEXPR } - void _Set_ptr_rep_and_enable_shared(nullptr_t, - _Ref_count_base* const _Rx) noexcept { // take ownership of nullptr + void _Set_ptr_rep_and_enable_shared(nullptr_t, _Ref_count_base* const _Rx) noexcept { // take ownership of nullptr this->_Ptr = nullptr; this->_Rep = _Rx; } @@ -1455,48 +1429,42 @@ void swap(shared_ptr<_Ty>& _Left, shared_ptr<_Ty>& _Right) noexcept { template _NODISCARD shared_ptr<_Ty1> static_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // static_cast for shared_ptr that properly respects the reference count - // control block + // static_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = static_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_Other, _Ptr); } template _NODISCARD shared_ptr<_Ty1> static_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // static_cast for shared_ptr that properly respects the reference count - // control block + // static_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = static_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_STD move(_Other), _Ptr); } template _NODISCARD shared_ptr<_Ty1> const_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // const_cast for shared_ptr that properly respects the reference count - // control block + // const_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = const_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_Other, _Ptr); } template _NODISCARD shared_ptr<_Ty1> const_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // const_cast for shared_ptr that properly respects the reference count - // control block + // const_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = const_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_STD move(_Other), _Ptr); } template _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // reinterpret_cast for shared_ptr that properly respects the reference count - // control block + // reinterpret_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = reinterpret_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_Other, _Ptr); } template _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // reinterpret_cast for shared_ptr that properly respects the reference count - // control block + // reinterpret_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = reinterpret_cast::element_type*>(_Other.get()); return shared_ptr<_Ty1>(_STD move(_Other), _Ptr); } @@ -1504,8 +1472,7 @@ _NODISCARD shared_ptr<_Ty1> reinterpret_pointer_cast(shared_ptr<_Ty2>&& _Other) #ifdef _CPPRTTI template _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>& _Other) noexcept { - // dynamic_cast for shared_ptr that properly respects the reference count - // control block + // dynamic_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = dynamic_cast::element_type*>(_Other.get()); if (_Ptr) { @@ -1517,8 +1484,7 @@ _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(const shared_ptr<_Ty2>& _Other) template _NODISCARD shared_ptr<_Ty1> dynamic_pointer_cast(shared_ptr<_Ty2>&& _Other) noexcept { - // dynamic_cast for shared_ptr that properly respects the reference count - // control block + // dynamic_cast for shared_ptr that properly respects the reference count control block const auto _Ptr = dynamic_cast::element_type*>(_Other.get()); if (_Ptr) { @@ -1551,8 +1517,7 @@ _Dx* get_deleter(const shared_ptr<_Ty>&) noexcept = delete; // requires static R // CLASS TEMPLATE _Ref_count_obj2 template -class _Ref_count_obj2 : public _Ref_count_base { // handle reference counting for object in - // control block, no allocator +class _Ref_count_obj2 : public _Ref_count_base { // handle reference counting for object in control block, no allocator public: template explicit _Ref_count_obj2(_Types&&... _Args) : _Ref_count_base() { @@ -1578,77 +1543,103 @@ private: }; #if _HAS_CXX20 +template +_Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { + return (_Val1 % _Val2 == 0) ? (_Val1 / _Val2) : (_Val1 / _Val2 + 1); +} + +template +void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, const size_t _Size) { + size_t _Idx = _Size; + do { + --_Idx; + if constexpr (rank_v<_Ty> > 0) { + _Reverse_destroy_multidimensional_n(_Arr[_Idx], extent_v<_Ty>); + } else { + _Destroy_in_place(_Arr[_Idx]); + } + } while (_Idx > 0); +} + template -void _Uninitialized_copy_md(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { - if constexpr (_STD rank_v<_Ty> > 0) { - for (size_t _It = 0; _It < _Size; ++_It) - _Uninitialized_copy_md(_In[_It], _Out[_It]); +void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { + if constexpr (rank_v<_Ty> > 0) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _TRY_BEGIN + _Uninitialized_copy_multidimensional(_In[_Idx], _Out[_Idx]); + _CATCH_ALL + _Reverse_destroy_multidimensional_n(_Out, _Idx - 1); + _RERAISE; + _CATCH_END + } } else { _STD uninitialized_copy_n(_In, _Size, _Out); } } template -void _Uninitialized_value_construct_md_n(_Ty* _Out, size_t _Size) { - if constexpr (_STD rank_v<_Ty> > 0) { - for (size_t _It = 0; _It < _Size; ++_It) - _Uninitialized_value_construct_md_n(_Out[_It], _STD extent_v<_Ty>); +void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { + if constexpr (rank_v<_Ty> > 0) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _TRY_BEGIN + _Uninitialized_value_construct_multidimensional_n(_Out[_Idx], extent_v<_Ty>); + _CATCH_ALL + _Reverse_destroy_multidimensional_n(_Out, _Idx - 1); + _RERAISE; + _CATCH_END + } } else { _Uninitialized_value_construct_n_unchecked1(_Out, _Size); } } template -void _Reverse_destroy_md_n(_Ty* _Arr, size_t _Size) { - size_t _It = _Size; - do { - --_It; - if constexpr (_STD rank_v<_Ty> > 0) { - _Reverse_destroy_md_n(_Arr[_It], _STD extent_v<_Ty>); - } else { - _Destroy_in_place(_Arr[_It]); +void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, const _Ty& _Val) { + if constexpr (rank_v<_Ty> > 0) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _TRY_BEGIN + _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); + _CATCH_ALL + _Reverse_destroy_multidimensional_n(_Out, _Idx - 1); + _RERAISE; + _CATCH_END } - } while (_It > 0); + } else { + _STD uninitialized_fill_n(_Out, _Size, _Val); + } } // CLASS TEMPLATE _Ref_count_unbounded_array template -class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array - // in control block, no allocator +class _Ref_count_unbounded_array + : public _Ref_count_base { // handle reference counting for unbounded array in control block, no allocator public: - explicit _Ref_count_unbounded_array(size_t _Count) : _Ref_count_base(), _Size(_Count) { - _Uninitialized_value_construct_md_n(_Get_ptr(), _Size); + explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { + _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); } - explicit _Ref_count_unbounded_array(size_t _Count, const _STD remove_extent_t<_Ty>& _Val) + explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) : _Ref_count_base(), _Size(_Count) { - if constexpr (_STD rank_v<_Ty> > 1) { - for (size_t _It = 0; _It < _Size; ++_It) - _Uninitialized_copy_md(_Val, _Get_ptr()[_It]); - } else { - _STD uninitialized_fill_n(_Get_ptr(), _Size, _Val); - } + _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Size, _Val); } - ~_Ref_count_unbounded_array() { - // nothing to do, _Storage was already destroyed in _Destroy - } - - size_t _Size; + ~_Ref_count_unbounded_array() = default; // nothing to do, _Storage was already destroyed in _Destroy auto _Get_ptr() { - return reinterpret_cast<_STD remove_extent_t<_Ty>*>( - reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); + return reinterpret_cast*>( + reinterpret_cast(this) + _Max_value(sizeof(*this), alignof(_Ty))); } private: + size_t _Size; + virtual void _Destroy() noexcept override { // destroy managed resource - _Reverse_destroy_md_n(_Get_ptr(), _Size); + _Reverse_destroy_multidimensional_n(_Get_ptr(), _Size); } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), - (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), + _Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -1656,18 +1647,13 @@ private: // CLASS TEMPLATE _Ref_count_bounded_array template -class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in - // control block, no allocator +class _Ref_count_bounded_array + : public _Ref_count_base { // handle reference counting for bounded array in control block, no allocator public: - explicit _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} + _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} - explicit _Ref_count_bounded_array(const _STD remove_extent_t<_Ty>& _Val) : _Ref_count_base() { - if constexpr (_STD rank_v<_Ty> > 1) { - for (size_t _It = 0; _It < _STD extent_v<_Ty>; ++_It) - _Uninitialized_copy_md(_Val, _Storage._Value[_It]); - } else { - _STD uninitialized_fill_n(_Storage._Value, _STD extent_v<_Ty>, _Val); - } + explicit _Ref_count_bounded_array(const remove_extent_t<_Ty>& _Val) : _Ref_count_base() { + _Uninitialized_fill_multidimensional_n(_Storage._Value, extent_v<_Ty>, _Val); } ~_Ref_count_bounded_array() { @@ -1688,6 +1674,7 @@ private: } }; #endif // _HAS_CXX20 + // CLASS TEMPLATE _Ebco_base template && !is_final_v<_Ty>> @@ -1763,37 +1750,65 @@ private: }; #if _HAS_CXX20 +template +void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, const size_t _Size, _Alloc& _Al) { + size_t _Idx = _Size; + do { + --_Idx; + if constexpr (rank_v<_Ty> > 0) { + _Reverse_destroy_multidimensional_n_al(_Arr[_Idx], extent_v<_Ty>, _Al); + } else { + allocator_traits<_Alloc>::destroy(_Al, _Arr + _Idx); + } + } while (_Idx > 0); +} + template -void _Uninitialized_copy_md_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], const _Alloc& _Al) { - if constexpr (_STD rank_v<_Ty> > 0) { - for (size_t _It = 0; _It < _Size; ++_It) - _Uninitialized_copy_md_al(_In[_It], _Out[_It], _Al); +void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], _Alloc& _Al) { + if constexpr (rank_v<_Ty> > 0) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _TRY_BEGIN + _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); + _CATCH_ALL + _Reverse_destroy_multidimensional_n_al(_Out, _Idx - 1, _Al); + _RERAISE; + _CATCH_END + } } else { _Uninitialized_copy(_In, _In + _Size, _Out, _Al); } } template -void _Uninitialized_value_construct_md_n_al(_Ty* _Out, size_t _Size, const _Alloc& _Al) { - if constexpr (_STD rank_v<_Ty> > 0) { - for (size_t _It = 0; _It < _Size; ++_It) - _Uninitialized_value_construct_md_n_al(_Out[_It], _STD extent_v<_Ty>, _Al); +void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const size_t _Size, _Alloc& _Al) { + if constexpr (rank_v<_Ty> > 0) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _TRY_BEGIN + _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); + _CATCH_ALL + _Reverse_destroy_multidimensional_n_al(_Out, _Idx - 1, _Al); + _RERAISE; + _CATCH_END + } } else { _Uninitialized_value_construct_n(_Out, _Size, _Al); } } template -void _Reverse_destroy_md_n_al(_Ty* _Arr, size_t _Size, const _Alloc& _Al) { - size_t _It = _Size; - do { - --_It; - if constexpr (_STD rank_v<_Ty> > 0) { - _Reverse_destroy_md_n_al(_Arr[_It], _STD extent_v<_Ty>, _Al); - } else { - allocator_traits::destroy(_Al, _Arr + _It); +void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Size, const _Ty& _Val, _Alloc& _Al) { + if constexpr (rank_v<_Ty> > 0) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _TRY_BEGIN + _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); + _CATCH_ALL + _Reverse_destroy_multidimensional_n_al(_Out, _Idx - 1, _Al); + _RERAISE; + _CATCH_END } - } while (_It > 0); + } else { + _Uninitialized_fill_n(_Out, _Size, _Val, _Al); + } } // CLASS TEMPLATE _Ref_count_unbounded_array_alloc @@ -1801,52 +1816,43 @@ template class __declspec(empty_bases) _Ref_count_unbounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { // handle reference counting for object in control block, allocator public: - explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, size_t _Count) + explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, const size_t _Count) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { - _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); - _Uninitialized_value_construct_md_n_al(_Get_ptr(), _Size, _Alty); + _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); + _Uninitialized_value_construct_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } explicit _Ref_count_unbounded_array_alloc( - const _Alloc& _Al_arg, size_t _Count, const _STD remove_extent_t<_Ty>& _Val) + const _Alloc& _Al_arg, const size_t _Count, const remove_extent_t<_Ty>& _Val) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { - _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); - if constexpr (_STD rank_v<_Ty> > 1) { - for (size_t _It = 0; _It < _Size; ++_It) - _Uninitialized_copy_md_al(_Val, _Get_ptr()[_It], _Alty); - } else { - _Uninitialized_fill_n(_Get_ptr(), _Size, _Val, _Alty); - } + _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); + _Uninitialized_fill_multidimensional_n_al(_Get_ptr(), _Size, _Val, _Alty); } - size_t _Size; - auto _Get_ptr() { - return reinterpret_cast<_STD remove_extent_t<_Ty>*>( - reinterpret_cast(this) + (_STD max)(sizeof(*this), alignof(_Ty))); + return reinterpret_cast*>( + reinterpret_cast(this) + _Max_value(sizeof(*this), alignof(_Ty))); } private: - ~_Ref_count_unbounded_array_alloc() { - // nothing to do; _Storage._Value already destroyed by _Destroy() - } + size_t _Size; + + ~_Ref_count_unbounded_array_alloc() = default; // nothing to do; _Storage._Value already destroyed by _Destroy() virtual void _Destroy() noexcept override { // destroy managed resource - _Maybe_rebind_alloc_t<_Alloc, _STD remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); - _Reverse_destroy_md_n_al(_Get_ptr(), _Size, _Alty); + _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } virtual void _Delete_this() noexcept override { // destroy self constexpr size_t _Max_alignment = - (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); - using _Storage = _STD aligned_storage_t<_Max_alignment, _Max_alignment>; - constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(*this) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = - static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); + _Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); + using _Storage = aligned_storage_t<_Max_alignment, _Max_alignment>; _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); this->~_Ref_count_unbounded_array_alloc(); allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), - static_cast(ceil(_Size * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size); + _Div_ceil(_Size * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + + _Max_value(sizeof(*this) / sizeof(_Storage), size_t(1))); } }; @@ -1856,19 +1862,14 @@ class __declspec(empty_bases) _Ref_count_bounded_array_alloc : public _Ebco_base // handle reference counting for object in control block, allocator public: explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { - _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); - _Uninitialized_value_construct_md_n_al(_Storage._Value, _STD extent_v<_Ty>, _Alty); + _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); + _Uninitialized_value_construct_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); } - explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg, const _STD remove_extent_t<_Ty>& _Val) + explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg, const remove_extent_t<_Ty>& _Val) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { - _Maybe_rebind_alloc_t<_Alloc, _STD remove_cv_t<_STD remove_all_extents_t<_Ty>>> _Alty(this->_Get_val()); - if constexpr (_STD rank_v<_Ty> > 1) { - for (size_t _It = 0; _It < _STD extent_v<_Ty>; ++_It) - _Uninitialized_copy_md_al(_Val, _Storage._Value[_It], _Alty); - } else { - _Uninitialized_fill_n(_Storage._Value, _STD extent_v<_Ty>, _Val, _Alty); - } + _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); + _Uninitialized_fill_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Val, _Alty); } union { @@ -1881,8 +1882,8 @@ private: } virtual void _Destroy() noexcept override { // destroy managed resource - _Maybe_rebind_alloc_t<_Alloc, _STD remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); - _Reverse_destroy_md_n_al(_Storage._Value, _STD extent_v<_Ty>, _Alty); + _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); } virtual void _Delete_this() noexcept override { // destroy self @@ -1895,9 +1896,9 @@ private: // FUNCTION TEMPLATE make_shared template -#if _HAS_CXX20 && __cpp_concepts -requires(!_STD is_array_v<_Ty>) -#endif // _HAS_CXX20 +#if _HAS_CXX20 && defined(__cpp_concepts) +requires(!is_array_v<_Ty>) +#endif // _HAS_CXX20 && defined(__cpp_concepts) _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; @@ -1905,43 +1906,49 @@ requires(!_STD is_array_v<_Ty>) return _Ret; } -#if _HAS_CXX20 && __cpp_concepts +#if _HAS_CXX20 && defined(__cpp_concepts) template -requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( +requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = - _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = - static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); - const auto _Rx = reinterpret_cast<_Refc*>( - new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); - new (_Rx) _Refc(_Count); + aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + const auto _Rx = + reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1))]); + _TRY_BEGIN + ::new (static_cast(_Rx)) _Refc(_Count); + _CATCH_ALL + delete[] reinterpret_cast<_Storage*>(_Rx); + _RERAISE; + _CATCH_END shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } template -requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared(size_t _Count, - const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array +requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( + size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = - _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = - static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); - const auto _Rx = reinterpret_cast<_Refc*>( - new _Storage[static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size]); - new (_Rx) _Refc(_Count, _Val); + aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + const auto _Rx = + reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1))]); + _TRY_BEGIN + ::new (static_cast(_Rx)) _Refc(_Count, _Val); + _CATCH_ALL + delete[] reinterpret_cast<_Storage*>(_Rx); + _RERAISE; + _CATCH_END shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } template -requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array +requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); @@ -1949,24 +1956,24 @@ requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared() { } template -requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( +requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); return _Ret; } -#endif // _HAS_CXX20 +#endif // _HAS_CXX20 && defined(__cpp_concepts) + // FUNCTION TEMPLATE allocate_shared template -#if _HAS_CXX20 && __cpp_concepts -requires(!_STD is_array_v<_Ty>) -#endif // _HAS_CXX20 - _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, - _Types&&... _Args) { // make a shared_ptr to non-array object - // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 - // (which controls whether allocator::construct sees T or const T when _Ty is - // const qualified) +#if _HAS_CXX20 && defined(__cpp_concepts) +requires(!is_array_v<_Ty>) +#endif // _HAS_CXX20 && defined(__cpp_concepts) + _NODISCARD shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object + // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether + // allocator::construct sees T or const T when _Ty is const qualified) using _Refoa = _Ref_count_obj_alloc2, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refoa>; _Alblock _Rebound(_Al); @@ -1979,69 +1986,79 @@ requires(!_STD is_array_v<_Ty>) return _Ret; } -#if _HAS_CXX20 && __cpp_concepts +#if _HAS_CXX20 && defined(__cpp_concepts) template -requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, - size_t _Count) { // make a shared_ptr to an unbounded array +requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al, size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = - _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = - static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); - _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate( - static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); - new (_Rx) _Refc(_Al, _Count); + aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); + size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Size)); + _TRY_BEGIN + ::new (static_cast(_Rx)) _Refc(_Al, _Count); + _CATCH_ALL + _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Size); + _RERAISE; + _CATCH_END shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } template -requires _STD is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, - const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array +requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, + const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = - _STD aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; - constexpr size_t _Rx_size_div_by_storage_size = (_STD max)(sizeof(_Refc) / sizeof(_Storage), size_t(1)); - constexpr double _Ty_size_div_by_storage_size = - static_cast(sizeof(_STD remove_extent_t<_Ty>)) / static_cast(sizeof(_Storage)); - _Rebind_alloc_t<_Alloc, _Refc> _Rebound(_Al); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate( - static_cast(ceil(_Count * _Ty_size_div_by_storage_size)) + _Rx_size_div_by_storage_size)); - new (_Rx) _Refc(_Al, _Count, _Val); + aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); + size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Size)); + _TRY_BEGIN + ::new (static_cast(_Rx)) _Refc(_Al, _Count, _Val); + _CATCH_ALL + _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Size); + _RERAISE; + _CATCH_END shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } template -requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( +requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); - const auto _Rx = _Rebound.allocate(1); - new (_Rx) _Refc(_Al); + _Alloc_construct_ptr<_Alblock> _Constructor{_Rebound}; + _Constructor._Allocate(); + ::new (static_cast(_Constructor._Ptr)) _Refc(_Al); shared_ptr<_Ty> _Ret; - _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); + const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); + _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); return _Ret; } template -requires _STD is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, - const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array +requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); - const auto _Rx = _Rebound.allocate(1); - new (_Rx) _Refc(_Al, _Val); + _Alloc_construct_ptr<_Alblock> _Constructor{_Rebound}; + _Constructor._Allocate(); + ::new (static_cast(_Constructor._Ptr)) _Refc(_Al, _Val); shared_ptr<_Ty> _Ret; - _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); + const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); + _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); return _Ret; } -#endif // _HAS_CXX20 +#endif // _HAS_CXX20 && defined(__cpp_concepts) // CLASS TEMPLATE weak_ptr template @@ -2049,20 +2066,17 @@ class weak_ptr : public _Ptr_base<_Ty> { // class for pointer to reference count public: constexpr weak_ptr() noexcept {} // construct empty weak_ptr object - weak_ptr(const weak_ptr& _Other) noexcept { // construct weak_ptr object for - // resource pointed to by _Other + weak_ptr(const weak_ptr& _Other) noexcept { // construct weak_ptr object for resource pointed to by _Other this->_Weakly_construct_from(_Other); } template ::value, int> = 0> - weak_ptr(const shared_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object - // for resource owned by _Other + weak_ptr(const shared_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for resource owned by _Other this->_Weakly_construct_from(_Other); } template ::value, int> = 0> - weak_ptr(const weak_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for - // resource pointed to by _Other + weak_ptr(const weak_ptr<_Ty2>& _Other) noexcept { // construct weak_ptr object for resource pointed to by _Other this->_Weakly_construct_from(_Other.lock()); } @@ -2139,8 +2153,7 @@ void swap(weak_ptr<_Ty>& _Left, weak_ptr<_Ty>& _Right) noexcept { // CLASS TEMPLATE enable_shared_from_this template -class enable_shared_from_this { // provide member functions that create - // shared_ptr to this +class enable_shared_from_this { // provide member functions that create shared_ptr to this public: using _Esft_type = enable_shared_from_this; @@ -2185,6 +2198,7 @@ private: mutable weak_ptr<_Ty> _Wptr; }; + // CLASS TEMPLATE unique_ptr AND HELPERS // STRUCT TEMPLATE default_delete @@ -2195,24 +2209,21 @@ struct default_delete { // default deleter for unique_ptr template , int> = 0> default_delete(const default_delete<_Ty2>&) noexcept {} - void operator()(_Ty* _Ptr) const noexcept - /* strengthened */ { // delete a pointer + void operator()(_Ty* _Ptr) const noexcept /* strengthened */ { // delete a pointer static_assert(0 < sizeof(_Ty), "can't delete an incomplete type"); delete _Ptr; } }; template -struct default_delete<_Ty[]> { // default deleter for unique_ptr to array of - // unknown size +struct default_delete<_Ty[]> { // default deleter for unique_ptr to array of unknown size constexpr default_delete() noexcept = default; template , int> = 0> default_delete(const default_delete<_Uty[]>&) noexcept {} template , int> = 0> - void operator()(_Uty* _Ptr) const noexcept - /* strengthened */ { // delete a pointer + void operator()(_Uty* _Ptr) const noexcept /* strengthened */ { // delete a pointer static_assert(0 < sizeof(_Uty), "can't delete an incomplete type"); delete[] _Ptr; } @@ -2225,8 +2236,7 @@ struct _Get_deleter_pointer_type { // provide fallback }; template -struct _Get_deleter_pointer_type<_Ty, _Dx_noref, - void_t> { // get _Dx_noref::pointer +struct _Get_deleter_pointer_type<_Ty, _Dx_noref, void_t> { // get _Dx_noref::pointer using type = typename _Dx_noref::pointer; }; @@ -2328,8 +2338,7 @@ public: return _Mypair._Get_first(); } - _NODISCARD add_lvalue_reference_t<_Ty> operator*() const noexcept - /* strengthened */ { + _NODISCARD add_lvalue_reference_t<_Ty> operator*() const noexcept /* strengthened */ { return *_Mypair._Myval2; } @@ -2378,13 +2387,12 @@ public: constexpr unique_ptr() noexcept : _Mypair(_Zero_then_variadic_args_t()) {} template > - using _Enable_ctor_reset = enable_if_t // - || _Is_nullptr::value // - || (is_same_v // - && is_pointer_v<_Uty> // - && is_convertible_v (*)[], - element_type (*)[]>)>; // TRANSITION, - // GH-248 + using _Enable_ctor_reset = + enable_if_t // + || _Is_nullptr::value // + || (is_same_v // + && is_pointer_v<_Uty> // + && is_convertible_v (*)[], element_type (*)[]>)>; // TRANSITION, GH-248 template = 0, class = _Enable_ctor_reset<_Uty>> explicit unique_ptr(_Uty _Ptr) noexcept : _Mypair(_Zero_then_variadic_args_t(), _Ptr) {} @@ -2423,9 +2431,9 @@ public: template ::pointer, class _UP_element_type = typename unique_ptr<_Uty, _Ex>::element_type> - using _Enable_conversion = enable_if_t, is_same, - is_same<_UP_pointer, _UP_element_type*>, is_convertible<_UP_element_type (*)[], element_type (*)[]>, - _More>>; // TRANSITION, GH-248 + using _Enable_conversion = enable_if_t< + conjunction_v, is_same, is_same<_UP_pointer, _UP_element_type*>, + is_convertible<_UP_element_type (*)[], element_type (*)[]>, _More>>; // TRANSITION, GH-248 template _Mypair; }; + // FUNCTION TEMPLATE make_unique template , int> = 0> _NODISCARD unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr @@ -2759,8 +2768,7 @@ inline void* align(size_t _Bound, size_t _Size, void*& _Ptr, size_t& _Space) noe #if _HAS_CXX20 && 0 template -_NODISCARD constexpr _Ty* assume_aligned(_Ty* _Ptr) noexcept -/* strengthened */ { +_NODISCARD constexpr _Ty* assume_aligned(_Ty* _Ptr) noexcept /* strengthened */ { // this enforces the requirement that _N0 be a power of two __builtin_assume_aligned(_Ptr, _N0); @@ -2775,8 +2783,7 @@ _CRTIMP2_PURE void __cdecl _Unlock_shared_ptr_spin_lock(); _END_EXTERN_C // WRAP SPIN-LOCK -struct _Shared_ptr_spin_lock { // class to manage a spin lock for shared_ptr - // atomic operations +struct _Shared_ptr_spin_lock { // class to manage a spin lock for shared_ptr atomic operations _Shared_ptr_spin_lock() { // lock the spin lock _Lock_shared_ptr_spin_lock(); } @@ -2813,8 +2820,7 @@ void atomic_store_explicit(shared_ptr<_Ty>* _Ptr, shared_ptr<_Ty> _Other, memory } template -void atomic_store(shared_ptr<_Ty>* _Ptr, - shared_ptr<_Ty> _Other) { // store _Other to *_Ptr atomically +void atomic_store(shared_ptr<_Ty>* _Ptr, shared_ptr<_Ty> _Other) { // store _Other to *_Ptr atomically _STD atomic_store_explicit(_Ptr, _STD move(_Other), memory_order_seq_cst); } From ab24fa635fef56ed789805f52489454235d4a9ab Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 21 Nov 2019 18:24:10 +0100 Subject: [PATCH 06/52] Transition LLVM-42404 --- stl/inc/memory | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 35af17f7279..858123c27a9 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1553,7 +1553,8 @@ void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, const size_t _Size) { size_t _Idx = _Size; do { --_Idx; - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { _Reverse_destroy_multidimensional_n(_Arr[_Idx], extent_v<_Ty>); } else { _Destroy_in_place(_Arr[_Idx]); @@ -1563,7 +1564,8 @@ void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, const size_t _Size) { template void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional(_In[_Idx], _Out[_Idx]); @@ -1579,7 +1581,8 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ template void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_value_construct_multidimensional_n(_Out[_Idx], extent_v<_Ty>); @@ -1595,7 +1598,8 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si template void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, const _Ty& _Val) { - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); @@ -1755,7 +1759,8 @@ void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, const size_t _Size, size_t _Idx = _Size; do { --_Idx; - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { _Reverse_destroy_multidimensional_n_al(_Arr[_Idx], extent_v<_Ty>, _Al); } else { allocator_traits<_Alloc>::destroy(_Al, _Arr + _Idx); @@ -1765,7 +1770,8 @@ void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, const size_t _Size, template void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], _Alloc& _Al) { - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); @@ -1781,7 +1787,8 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out template void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const size_t _Size, _Alloc& _Al) { - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); @@ -1797,7 +1804,8 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const template void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Size, const _Ty& _Val, _Alloc& _Al) { - if constexpr (rank_v<_Ty> > 0) { + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); From 38e6b83b3b1e24b39fb05ba0902dc7134815d100 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 21 Nov 2019 19:05:40 +0100 Subject: [PATCH 07/52] More Fixes --- stl/inc/memory | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 858123c27a9..4c89d03ba01 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1544,7 +1544,7 @@ private: #if _HAS_CXX20 template -_Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { +constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { return (_Val1 % _Val2 == 0) ? (_Val1 / _Val2) : (_Val1 / _Val2 + 1); } @@ -1631,7 +1631,7 @@ public: auto _Get_ptr() { return reinterpret_cast*>( - reinterpret_cast(this) + _Max_value(sizeof(*this), alignof(_Ty))); + reinterpret_cast(this) + _Div_ceil(sizeof(*this), alignof(_Ty)) * alignof(_Ty)); } private: @@ -1839,7 +1839,7 @@ public: auto _Get_ptr() { return reinterpret_cast*>( - reinterpret_cast(this) + _Max_value(sizeof(*this), alignof(_Ty))); + reinterpret_cast(this) + _Div_ceil(sizeof(*this), alignof(_Ty)) * alignof(_Ty)); } private: @@ -1860,7 +1860,7 @@ private: this->~_Ref_count_unbounded_array_alloc(); allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), _Div_ceil(_Size * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Max_value(sizeof(*this) / sizeof(_Storage), size_t(1))); + + _Div_ceil(sizeof(*this), sizeof(_Storage))); } }; @@ -1923,7 +1923,7 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1))]); + + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Count); _CATCH_ALL @@ -1943,7 +1943,7 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1))]); + + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Count, _Val); _CATCH_ALL @@ -2002,8 +2002,8 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); - size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + size_t _Size = + _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Size)); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Al, _Count); @@ -2023,8 +2023,8 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(co using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); - size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Max_value(sizeof(_Refc) / sizeof(_Storage), size_t(1)); + size_t _Size = + _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Size)); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Al, _Count, _Val); From a586cd86fec8d877e04770981ee0bd704182bdc6 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 28 Nov 2019 17:51:48 +0100 Subject: [PATCH 08/52] Formatting of requires clauses --- stl/inc/memory | 86 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 58 insertions(+), 28 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 4c89d03ba01..d8b17136b24 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1252,47 +1252,61 @@ private: _Owner._Call_deleter = false; } + // clang-format off template #if _HAS_CXX20 && defined(__cpp_concepts) - requires(!is_array_v<_Ty0>) + requires(!is_array_v<_Ty0>) #endif // _HAS_CXX20 && defined(__cpp_concepts) - friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); + friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); + // clang-format on #if _HAS_CXX20 && defined(__cpp_concepts) + // clang-format off template - requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(size_t _Count); + requires is_unbounded_array_v<_Ty0> + friend shared_ptr<_Ty0> make_shared(const size_t _Count); template - requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared( - size_t _Count, const remove_extent_t<_Ty0>& _Val); + requires is_unbounded_array_v<_Ty0> + friend shared_ptr<_Ty0> make_shared(const size_t _Count, const remove_extent_t<_Ty0>& _Val); template - requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(); + requires is_bounded_array_v<_Ty0> + friend shared_ptr<_Ty0> make_shared(); template - requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); + requires is_bounded_array_v<_Ty0> + friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); + // clang-format on #endif // _HAS_CXX20 && defined(__cpp_concepts) + // clang-format off template #if _HAS_CXX20 && defined(__cpp_concepts) requires(!is_array_v<_Ty0>) #endif // _HAS_CXX20 && defined(__cpp_concepts) friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + // clang-format on #if _HAS_CXX20 && defined(__cpp_concepts) + // clang-format off template - requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, size_t _Count); + requires is_unbounded_array_v<_Ty0> + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const size_t _Count); template - requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared( - const _Alloc& _Al_arg, size_t _Count, const remove_extent_t<_Ty0>& _Val); + requires is_unbounded_array_v<_Ty0> + friend shared_ptr<_Ty0> allocate_shared( + const _Alloc& _Al_arg, const size_t _Count, const remove_extent_t<_Ty0>& _Val); template - requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg); + requires is_bounded_array_v<_Ty0> + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg); template - requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared( - const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); + requires is_bounded_array_v<_Ty0> + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); + // clang-format on #endif // _HAS_CXX20 && defined(__cpp_concepts) template @@ -1903,21 +1917,25 @@ private: #endif // _HAS_CXX20 // FUNCTION TEMPLATE make_shared +// clang-format off template #if _HAS_CXX20 && defined(__cpp_concepts) -requires(!is_array_v<_Ty>) + requires(!is_array_v<_Ty>) #endif // _HAS_CXX20 && defined(__cpp_concepts) - _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object +_NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_STD addressof(_Rx->_Storage._Value), _Rx); return _Ret; } +// clang-format on #if _HAS_CXX20 && defined(__cpp_concepts) +// clang-format off template -requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( - size_t _Count) { // make a shared_ptr to an unbounded array + requires is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared( + const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; @@ -1936,8 +1954,9 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( } template -requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( - size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array + requires is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared( + const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; @@ -1956,7 +1975,8 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( } template -requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array + requires is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); @@ -1964,21 +1984,24 @@ requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared() { // m } template -requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> make_shared( + requires is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> make_shared( const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); return _Ret; } +// clang-format on #endif // _HAS_CXX20 && defined(__cpp_concepts) // FUNCTION TEMPLATE allocate_shared +// clang-format off template #if _HAS_CXX20 && defined(__cpp_concepts) -requires(!is_array_v<_Ty>) + requires(!is_array_v<_Ty>) #endif // _HAS_CXX20 && defined(__cpp_concepts) - _NODISCARD shared_ptr<_Ty> allocate_shared( +_NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether // allocator::construct sees T or const T when _Ty is const qualified) @@ -1993,11 +2016,14 @@ requires(!is_array_v<_Ty>) _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); return _Ret; } +// clang-format on #if _HAS_CXX20 && defined(__cpp_concepts) +// clang-format off template -requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( - const _Alloc& _Al, size_t _Count) { // make a shared_ptr to an unbounded array + requires is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared( + const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; @@ -2017,7 +2043,8 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( } template -requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, size_t _Count, + requires is_unbounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = @@ -2038,7 +2065,8 @@ requires is_unbounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared(co } template -requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( + requires is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -2053,7 +2081,8 @@ requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( } template -requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( + requires is_bounded_array_v<_Ty> +_NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -2066,6 +2095,7 @@ requires is_bounded_array_v<_Ty> _NODISCARD shared_ptr<_Ty> allocate_shared( _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); return _Ret; } +// clang-format on #endif // _HAS_CXX20 && defined(__cpp_concepts) // CLASS TEMPLATE weak_ptr From 77db877696445e2c5577c084cbe82491259c6a8c Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 28 Nov 2019 21:46:10 +0100 Subject: [PATCH 09/52] Removed checking for _HAS_CXX20 --- stl/inc/memory | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index d8b17136b24..d8015339e33 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1254,13 +1254,13 @@ private: // clang-format off template -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) requires(!is_array_v<_Ty0>) -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); // clang-format on -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) // clang-format off template requires is_unbounded_array_v<_Ty0> @@ -1278,17 +1278,17 @@ private: requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); // clang-format on -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) // clang-format off template -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) requires(!is_array_v<_Ty0>) -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); // clang-format on -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) // clang-format off template requires is_unbounded_array_v<_Ty0> @@ -1307,7 +1307,7 @@ private: requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); // clang-format on -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) template void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px @@ -1556,7 +1556,7 @@ private: } }; -#if _HAS_CXX20 +#if defined(__cpp_concepts) template constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { return (_Val1 % _Val2 == 0) ? (_Val1 / _Val2) : (_Val1 / _Val2 + 1); @@ -1691,7 +1691,7 @@ private: delete this; } }; -#endif // _HAS_CXX20 +#endif // defined(__cpp_concepts) // CLASS TEMPLATE _Ebco_base template void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, const size_t _Size, _Alloc& _Al) { size_t _Idx = _Size; @@ -1914,14 +1914,14 @@ private: _Deallocate_plain(_Al, this); } }; -#endif // _HAS_CXX20 +#endif // defined(__cpp_concepts) // FUNCTION TEMPLATE make_shared // clang-format off template -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) requires(!is_array_v<_Ty>) -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; @@ -1930,7 +1930,7 @@ _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr } // clang-format on -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) // clang-format off template requires is_unbounded_array_v<_Ty> @@ -1993,14 +1993,14 @@ _NODISCARD shared_ptr<_Ty> make_shared( return _Ret; } // clang-format on -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) // FUNCTION TEMPLATE allocate_shared // clang-format off template -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) requires(!is_array_v<_Ty>) -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) _NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether @@ -2018,7 +2018,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( } // clang-format on -#if _HAS_CXX20 && defined(__cpp_concepts) +#if defined(__cpp_concepts) // clang-format off template requires is_unbounded_array_v<_Ty> @@ -2096,7 +2096,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( return _Ret; } // clang-format on -#endif // _HAS_CXX20 && defined(__cpp_concepts) +#endif // defined(__cpp_concepts) // CLASS TEMPLATE weak_ptr template From 5bb85afcda0597491d93844461147faafb0552bb Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Fri, 29 Nov 2019 09:59:34 +0100 Subject: [PATCH 10/52] Remove indentation before friend declaration --- stl/inc/memory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/memory b/stl/inc/memory index d8015339e33..610838704cf 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1285,7 +1285,7 @@ private: #if defined(__cpp_concepts) requires(!is_array_v<_Ty0>) #endif // defined(__cpp_concepts) - friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); // clang-format on #if defined(__cpp_concepts) From 458424cbc9e2d0f193efbd1d8c7e23597ceb29c3 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Fri, 29 Nov 2019 10:06:31 +0100 Subject: [PATCH 11/52] Add indentation before requires clause --- stl/inc/memory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/memory b/stl/inc/memory index 610838704cf..dd7629f417f 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1283,7 +1283,7 @@ private: // clang-format off template #if defined(__cpp_concepts) - requires(!is_array_v<_Ty0>) + requires(!is_array_v<_Ty0>) #endif // defined(__cpp_concepts) friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); // clang-format on From d778d04a6292734563fd773365c34e43c1f0b338 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Fri, 29 Nov 2019 20:01:03 +0100 Subject: [PATCH 12/52] Fix destruction if initialization throws --- stl/inc/memory | 193 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 161 insertions(+), 32 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index dd7629f417f..595814cb63f 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1562,18 +1562,54 @@ constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { return (_Val1 % _Val2 == 0) ? (_Val1 / _Val2) : (_Val1 / _Val2 + 1); } +template +struct _Uninitialized_rev_destroying_backout { // struct to undo partially constructed ranges in _Uninitialized_xxx + // algorithms + _NoThrowIt _First; + _NoThrowIt _Last; + + explicit _Uninitialized_rev_destroying_backout(_NoThrowIt _Dest) : _First(_Dest), _Last(_Dest) {} + + _Uninitialized_rev_destroying_backout(_NoThrowIt _First_, _NoThrowIt _Last_) : _First(_First_), _Last(_Last_) {} + + _Uninitialized_rev_destroying_backout(const _Uninitialized_rev_destroying_backout&) = delete; + _Uninitialized_rev_destroying_backout& operator=(const _Uninitialized_rev_destroying_backout&) = delete; + + ~_Uninitialized_rev_destroying_backout() { + if (_Last != _First) { + do { + --_Last; + _STD destroy_at(_Last); + } while (_Last != _First); + } + } + + template + void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment + _Construct_in_place(*_Last, _STD forward<_Types>(_Vals)...); + ++_Last; + } + + _NoThrowIt _Release() { // suppress any exception handling backout and return _Last + _First = _Last; + return _Last; + } +}; + template void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, const size_t _Size) { - size_t _Idx = _Size; - do { - --_Idx; - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { - _Reverse_destroy_multidimensional_n(_Arr[_Idx], extent_v<_Ty>); - } else { - _Destroy_in_place(_Arr[_Idx]); - } - } while (_Idx > 0); + if (_Size != 0) { + size_t _Idx = _Size; + do { + --_Idx; + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { + _Reverse_destroy_multidimensional_n(_Arr[_Idx], extent_v<_Ty>); + } else { + _Destroy_in_place(_Arr[_Idx]); + } + } while (_Idx > 0); + } } template @@ -1584,12 +1620,20 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ _TRY_BEGIN _Uninitialized_copy_multidimensional(_In[_Idx], _Out[_Idx]); _CATCH_ALL - _Reverse_destroy_multidimensional_n(_Out, _Idx - 1); + _Reverse_destroy_multidimensional_n(_Out, _Idx); _RERAISE; _CATCH_END } } else { - _STD uninitialized_copy_n(_In, _Size, _Out); + if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { + _Copy_memmove(_In, _In + _Size, _Out); + } else { + _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _Backout._Emplace_back(_In[_Idx]); + } + _Backout._Release(); + } } } @@ -1601,12 +1645,20 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si _TRY_BEGIN _Uninitialized_value_construct_multidimensional_n(_Out[_Idx], extent_v<_Ty>); _CATCH_ALL - _Reverse_destroy_multidimensional_n(_Out, _Idx - 1); + _Reverse_destroy_multidimensional_n(_Out, _Idx); _RERAISE; _CATCH_END } } else { - _Uninitialized_value_construct_n_unchecked1(_Out, _Size); + if constexpr (_Use_memset_value_construct_v<_Ty*>) { + _Zero_range(_Out, _Out + _Size); + } else { + _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(); + } + _Backout._Release(); + } } } @@ -1618,12 +1670,22 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, _TRY_BEGIN _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); _CATCH_ALL - _Reverse_destroy_multidimensional_n(_Out, _Idx - 1); + _Reverse_destroy_multidimensional_n(_Out, _Idx); _RERAISE; _CATCH_END } } else { - _STD uninitialized_fill_n(_Out, _Size, _Val); + if (0 < _Size) { + if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { + _CSTD memset(_Out, static_cast(_Val), _Size); + } else { + _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(_Val); + } + _Backout._Release(); + } + } } } @@ -1768,18 +1830,57 @@ private: }; #if defined(__cpp_concepts) +template +class _Uninitialized_rev_destroying_backout_al { // struct to undo partially constructed ranges in + // _Uninitialized_xxx_al algorithms + using pointer = _Alloc_ptr_t<_Alloc>; + +public: + _Uninitialized_rev_destroying_backout_al(pointer _Dest, _Alloc& _Al_) : _First(_Dest), _Last(_Dest), _Al(_Al_) {} + + _Uninitialized_rev_destroying_backout_al(const _Uninitialized_rev_destroying_backout_al&) = delete; + _Uninitialized_rev_destroying_backout_al& operator=(const _Uninitialized_rev_destroying_backout_al&) = delete; + + ~_Uninitialized_rev_destroying_backout_al() { + if (_Last != _First) { + do { + --_Last; + allocator_traits<_Alloc>::destroy(_Al, _Last); + } while (_Last != _First); + } + } + + template + void _Emplace_back(_Types&&... _Vals) { // construct a new element at *_Last and increment + allocator_traits<_Alloc>::construct(_Al, _Unfancy(_Last), _STD forward<_Types>(_Vals)...); + ++_Last; + } + + pointer _Release() { // suppress any exception handling backout and return _Last + _First = _Last; + return _Last; + } + +private: + pointer _First; + pointer _Last; + _Alloc& _Al; +}; + template void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, const size_t _Size, _Alloc& _Al) { - size_t _Idx = _Size; - do { - --_Idx; - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { - _Reverse_destroy_multidimensional_n_al(_Arr[_Idx], extent_v<_Ty>, _Al); - } else { - allocator_traits<_Alloc>::destroy(_Al, _Arr + _Idx); - } - } while (_Idx > 0); + if (_Size != 0) { + size_t _Idx = _Size; + do { + --_Idx; + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { + _Reverse_destroy_multidimensional_n_al(_Arr[_Idx], extent_v<_Ty>, _Al); + } else { + allocator_traits<_Alloc>::destroy(_Al, _Arr + _Idx); + } + } while (_Idx > 0); + } } template @@ -1790,12 +1891,22 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out _TRY_BEGIN _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); _CATCH_ALL - _Reverse_destroy_multidimensional_n_al(_Out, _Idx - 1, _Al); + _Reverse_destroy_multidimensional_n_al(_Out, _Idx, _Al); _RERAISE; _CATCH_END } } else { - _Uninitialized_copy(_In, _In + _Size, _Out, _Al); + if constexpr (conjunction_v::_Really_trivial>, + _Uses_default_construct<_Alloc, _Ty*, _Ty>>) { + _Copy_memmove(_In, _In + _Size, _Out); + (void) _Al; + } else { + _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _Backout._Emplace_back(_In[_Idx]); + } + _Backout._Release(); + } } } @@ -1807,12 +1918,21 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const _TRY_BEGIN _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); _CATCH_ALL - _Reverse_destroy_multidimensional_n_al(_Out, _Idx - 1, _Al); + _Reverse_destroy_multidimensional_n_al(_Out, _Idx, _Al); _RERAISE; _CATCH_END } } else { - _Uninitialized_value_construct_n(_Out, _Size, _Al); + if constexpr (_Use_memset_value_construct_v<_Ty*> && _Uses_default_construct<_Alloc, _Ty*>::value) { + (void) _Al; + _Zero_range(_Out, _Out + _Size); + } else { + _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(); + } + _Backout._Release(); + } } } @@ -1824,12 +1944,21 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si _TRY_BEGIN _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); _CATCH_ALL - _Reverse_destroy_multidimensional_n_al(_Out, _Idx - 1, _Al); + _Reverse_destroy_multidimensional_n_al(_Out, _Idx, _Al); _RERAISE; _CATCH_END } } else { - _Uninitialized_fill_n(_Out, _Size, _Val, _Al); + if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { + (void) _Al; + _CSTD memset(_Out, static_cast(_Val), static_cast(_Size)); + } else { + _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(_Val); + } + _Backout._Release(); + } } } From 53f3c4d81d1187ed9f3d07df9220758208d8184d Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 5 Dec 2019 17:33:59 +0100 Subject: [PATCH 13/52] Feature-test macro --- stl/inc/yvals_core.h | 226 ++++++++++++++++++++++++------------------- 1 file changed, 128 insertions(+), 98 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index fb878fb2c2a..70b1272b954 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -18,44 +18,46 @@ #endif // _STL_COMPILER_PREPROCESSOR #if _STL_COMPILER_PREPROCESSOR -// _HAS_CXX20 directly controls: -// P0020R6 atomic, atomic, atomic -// P0318R1 unwrap_reference, unwrap_ref_decay -// P0325R4 to_array() -// P0356R5 bind_front() -// P0439R0 enum class memory_order -// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view -// P0458R2 contains() For Ordered And Unordered Associative Containers -// P0463R1 endian -// P0482R6 Library Support For char8_t -// (mbrtoc8 and c8rtomb not yet implemented) -// P0487R1 Fixing operator>>(basic_istream&, CharT*) -// P0550R2 remove_cvref -// P0616R0 Using move() In -// P0631R8 Math Constants -// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type -// P0653R2 to_address() -// P0655R1 visit() -// P0674R1 make_shared() For Arrays -// P0758R1 is_nothrow_convertible -// P0768R1 Library Support For The Spaceship Comparison Operator <=> -// (partially implemented) -// P0769R2 shift_left(), shift_right() -// P0811R3 midpoint(), lerp() -// (partially implemented, lerp() not yet constexpr) -// P0887R1 type_identity -// P0896R4 Ranges -// (partially implemented) -// P0898R3 Standard Library Concepts -// P0919R3 Heterogeneous Lookup For Unordered Containers -// P0966R1 string::reserve() Should Not Shrink -// P1209R0 erase_if(), erase() -// P1227R2 Signed std::ssize(), Unsigned span::size() -// (partially implemented) -// P1357R1 is_bounded_array, is_unbounded_array -// P1651R0 bind_front() Should Not Unwrap reference_wrapper -// P1754R1 Rename Concepts To standard_case -// P????R? directory_entry::clear_cache() +// Implemented unconditionally: +// N3911 void_t +// N4089 Safe Conversions In unique_ptr +// N4169 invoke() +// N4258 noexcept Cleanups +// N4259 uncaught_exceptions() +// N4277 Trivially Copyable reference_wrapper +// N4279 insert_or_assign()/try_emplace() For map/unordered_map +// N4280 size(), empty(), data() +// N4366 Precisely Constraining unique_ptr Assignment +// N4387 Improving pair And tuple +// N4389 bool_constant +// N4508 shared_mutex (Untimed) +// N4510 Supporting Incomplete Types In vector/list/forward_list +// P0006R0 Variable Templates For Type Traits (is_same_v, etc.) +// P0007R1 as_const() +// P0013R1 Logical Operator Type Traits (conjunction, etc.) +// P0033R1 Rewording enable_shared_from_this +// P0063R3 C11 Standard Library +// P0074R0 owner_less<> +// P0092R1 floor(), ceil(), round(), abs() +// P0340R3 SFINAE-Friendly underlying_type +// P0414R2 shared_ptr, shared_ptr +// P0418R2 atomic compare_exchange memory_order Requirements +// P0435R1 Overhauling common_type +// P0497R0 Fixing shared_ptr For Arrays +// P0513R0 Poisoning hash +// P0516R0 Marking shared_future Copying As noexcept +// P0517R0 Constructing future_error From future_errc +// P0548R1 Tweaking common_type And duration +// P0558R1 Resolving atomic Named Base Class Inconsistencies +// P0599R1 noexcept hash +// P0738R2 istream_iterator Cleanup +// P0771R1 noexcept For std::function's Move Constructor +// P0777R1 Avoiding Unnecessary decay +// P0809R0 Comparing Unordered Containers +// P0941R2 Feature-Test Macros +// P0972R0 noexcept For zero(), min(), max() +// P1164R1 Making create_directory() Intuitive +// P1902R1 Missing Feature-Test Macros 2017-2019 // _HAS_CXX17 directly controls: // P0005R4 not_fn() @@ -117,63 +119,64 @@ // The non-Standard std::tr1 namespace and TR1-only machinery // Enforcement of matching allocator value_types -// _HAS_NODISCARD (in vcruntime.h) controls: -// [[nodiscard]] attributes on STL functions - // _HAS_CXX17 and _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS control: // P0174R2 Deprecating Vestigial Library Parts // P0521R0 Deprecating shared_ptr::unique() // P0618R0 Deprecating // Other C++17 deprecation warnings +// _HAS_CXX20 directly controls: +// P0020R6 atomic, atomic, atomic +// P0318R1 unwrap_reference, unwrap_ref_decay +// P0325R4 to_array() +// P0356R5 bind_front() +// P0439R0 enum class memory_order +// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view +// P0458R2 contains() For Ordered And Unordered Associative Containers +// P0463R1 endian +// P0482R6 Library Support For char8_t +// (mbrtoc8 and c8rtomb not yet implemented) +// P0487R1 Fixing operator>>(basic_istream&, CharT*) +// P0550R2 remove_cvref +// P0553R4 Rotating And Counting Functions +// P0556R3 ispow2(), ceil2(), floor2(), log2p1() +// (log2p1() is called bit_length() as of D1956) +// P0595R2 is_constant_evaluated() +// P0616R0 Using move() In +// P0631R8 Math Constants +// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type +// P0653R2 to_address() +// P0655R1 visit() +// P0674R1 make_shared() For Arrays +// P0758R1 is_nothrow_convertible +// P0768R1 Library Support For The Spaceship Comparison Operator <=> +// (partially implemented) +// P0769R2 shift_left(), shift_right() +// P0811R3 midpoint(), lerp() +// (partially implemented, lerp() not yet constexpr) +// P0887R1 type_identity +// P0896R4 Ranges +// (partially implemented) +// P0898R3 Standard Library Concepts +// P0919R3 Heterogeneous Lookup For Unordered Containers +// P0966R1 string::reserve() Should Not Shrink +// P1209R0 erase_if(), erase() +// P1227R2 Signed std::ssize(), Unsigned span::size() +// (partially implemented) +// P1357R1 is_bounded_array, is_unbounded_array +// P1612R1 Relocating endian To +// P1651R0 bind_front() Should Not Unwrap reference_wrapper +// P1690R1 Refining Heterogeneous Lookup For Unordered Containers +// P1754R1 Rename Concepts To standard_case +// P????R? directory_entry::clear_cache() + // _HAS_CXX20 and _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS control: // P0767R1 Deprecating is_pod // Other C++20 deprecation warnings -// Implemented unconditionally: -// N3911 void_t -// N4089 Safe Conversions In unique_ptr -// N4169 invoke() -// N4258 noexcept Cleanups -// N4259 uncaught_exceptions() -// N4277 Trivially Copyable reference_wrapper -// N4279 insert_or_assign()/try_emplace() For map/unordered_map -// N4280 size(), empty(), data() -// N4366 Precisely Constraining unique_ptr Assignment -// N4387 Improving pair And tuple -// N4389 bool_constant -// N4508 shared_mutex (Untimed) -// N4510 Supporting Incomplete Types In vector/list/forward_list -// P0006R0 Variable Templates For Type Traits (is_same_v, etc.) -// P0007R1 as_const() -// P0013R1 Logical Operator Type Traits (conjunction, etc.) -// P0033R1 Rewording enable_shared_from_this -// P0063R3 C11 Standard Library -// P0074R0 owner_less<> -// P0092R1 floor(), ceil(), round(), abs() -// P0340R3 SFINAE-Friendly underlying_type -// P0414R2 shared_ptr, shared_ptr -// P0418R2 atomic compare_exchange memory_order Requirements -// P0435R1 Overhauling common_type -// P0497R0 Fixing shared_ptr For Arrays -// P0513R0 Poisoning hash -// P0516R0 Marking shared_future Copying As noexcept -// P0517R0 Constructing future_error From future_errc -// P0548R1 Tweaking common_type And duration -// P0558R1 Resolving atomic Named Base Class Inconsistencies -// P0599R1 noexcept hash -// P0738R2 istream_iterator Cleanup -// P0771R1 noexcept For std::function's Move Constructor -// P0777R1 Avoiding Unnecessary decay -// P0809R0 Comparing Unordered Containers -// P0941R2 Feature-Test Macros -// P0972R0 noexcept For zero(), min(), max() -// P1164R1 Making create_directory() Intuitive - // Parallel Algorithms Notes -// C++ allows an implementation to implement parallel algorithms as calls to the -// serial algorithms. This implementation parallelizes several common algorithm -// calls, but not all. +// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. +// This implementation parallelizes several common algorithm calls, but not all. // // The following algorithms are parallelized. // * adjacent_difference @@ -218,9 +221,8 @@ // // The following are not presently parallelized: // -// No apparent parallelism performance improvement on target hardware; all -// algorithms which merely copy or permute elements with no branches are -// typically memory bandwidth limited. +// No apparent parallelism performance improvement on target hardware; all algorithms which +// merely copy or permute elements with no branches are typically memory bandwidth limited. // * copy // * copy_n // * fill @@ -234,8 +236,7 @@ // * shift_right // * swap_ranges // -// Confusion over user parallelism requirements exists; likely in the above -// category anyway. +// Confusion over user parallelism requirements exists; likely in the above category anyway. // * generate // * generate_n // @@ -243,8 +244,7 @@ // * partial_sort // * partial_sort_copy // -// Not yet evaluated; parallelism may be implemented in a future release and is -// suspected to be beneficial. +// Not yet evaluated; parallelism may be implemented in a future release and is suspected to be beneficial. // * copy_if // * includes // * inplace_merge @@ -284,6 +284,9 @@ #error _STL_WARNING_LEVEL cannot be greater than 4. #endif // _STL_WARNING_LEVEL > 4 +// _HAS_NODISCARD (in vcruntime.h) controls: +// [[nodiscard]] attributes on STL functions + // Controls whether the STL uses "if constexpr" internally #ifndef _HAS_IF_CONSTEXPR #ifdef __CUDACC__ @@ -893,7 +896,7 @@ #ifndef _USING_V110_SDK71_ #define __cpp_lib_shared_mutex 201505L #endif // _USING_V110_SDK71_ -#define __cpp_lib_shared_ptr_arrays 201611L +#define __cpp_lib_shared_ptr_arrays 201707L #define __cpp_lib_transparent_operators 201510L #define __cpp_lib_type_trait_variable_templates 201510L #define __cpp_lib_uncaught_exceptions 201411L @@ -903,7 +906,7 @@ #if _HAS_CXX17 #define __cpp_lib_any 201606L #define __cpp_lib_apply 201603L -#define __cpp_lib_array_constexpr 201603L +#define __cpp_lib_array_constexpr 201803L #define __cpp_lib_atomic_is_always_lock_free 201603L #define __cpp_lib_boyer_moore_searcher 201603L #if _HAS_STD_BYTE @@ -936,7 +939,7 @@ #define __cpp_lib_sample 201603L #define __cpp_lib_scoped_lock 201703L #define __cpp_lib_shared_ptr_weak_type 201606L -#define __cpp_lib_string_view 201606L +#define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L #define __cpp_lib_variant 201606L #else // _HAS_CXX17 @@ -945,8 +948,18 @@ // C++20 #if _HAS_CXX20 -#define __cpp_lib_bind_front 201907L +#define __cpp_lib_atomic_float 201711L +#define __cpp_lib_bind_front 201907L + +#if defined(__clang__) || defined(__EDG__) +#define __cpp_lib_bitops 201907L +#else // ^^^ Clang and EDG / MSVC vvv +// a future MSVC update will embed CPU feature detection into intrinsics +// TRANSITION, VSO-1020212 +#endif // defined(__clang__) || defined(__EDG__) + #define __cpp_lib_bounded_array_traits 201902L + #ifdef __cpp_char8_t #define __cpp_lib_char8_t 201811L #endif // __cpp_char8_t @@ -960,11 +973,27 @@ #endif // _HAS_STD_BOOLEAN #endif // defined(__cpp_concepts) && __cpp_concepts > 201507L +#define __cpp_lib_endian 201907L #define __cpp_lib_erase_if 201811L #define __cpp_lib_generic_unordered_lookup 201811L -#define __cpp_lib_list_remove_return_type 201806L -#define __cpp_lib_math_constants 201907L -#define __cpp_lib_to_array 201907L +#define __cpp_lib_int_pow2 201806L + +#if defined(__clang__) || defined(__EDG__) \ + || (defined(_MSC_VER) && _MSC_VER >= 1925 && !(_MSC_FULL_VER == 192528318 && _MSC_BUILD == 97)) +#define __cpp_lib_is_constant_evaluated 201811L +#endif // TRANSITION, VS 2019 16.5 Preview 2 and toolset update + +#define __cpp_lib_list_remove_return_type 201806L +#define __cpp_lib_math_constants 201907L +#define __cpp_lib_nothrow_convertible 201806L +#define __cpp_lib_remove_cvref 201711L +#define __cpp_lib_shift 201806L +#define __cpp_lib_ssize 201902L +#define __cpp_lib_starts_ends_with 201711L +#define __cpp_lib_to_address 201711L +#define __cpp_lib_to_array 201907L +#define __cpp_lib_type_identity 201806L +#define __cpp_lib_unwrap_ref 201811L #endif // _HAS_CXX20 // EXPERIMENTAL @@ -995,6 +1024,7 @@ compiler option, or define _ALLOW_RTCc_IN_STL to acknowledge that you have recei #define _STD_BEGIN namespace std { #define _STD_END } #define _STD ::std:: +#define _RANGES ::std::ranges:: // We use the stdext (standard extension) namespace to contain extensions that are not part of the current standard #define _STDEXT_BEGIN namespace stdext { From 11d8d937f31ba4e2e232eede7aa1dccfd57f19c8 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 5 Dec 2019 18:24:36 +0100 Subject: [PATCH 14/52] Correct Encoding --- stl/inc/yvals_core.h | 2130 +++++++++++++++++++++--------------------- 1 file changed, 1065 insertions(+), 1065 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 19d7213f923..70b1272b954 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1,1065 +1,1065 @@ -// yvals_core.h internal header (core) - -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#pragma once -#ifndef _YVALS_CORE_H_ -#define _YVALS_CORE_H_ -#ifndef _STL_COMPILER_PREPROCESSOR -// All STL headers avoid exposing their contents when included by various -// non-C++-compiler tools to avoid breaking builds when we use newer language -// features in the headers than such tools understand. -#if defined(RC_INVOKED) || defined(Q_MOC_RUN) || defined(__midl) -#define _STL_COMPILER_PREPROCESSOR 0 -#else -#define _STL_COMPILER_PREPROCESSOR 1 -#endif -#endif // _STL_COMPILER_PREPROCESSOR - -#if _STL_COMPILER_PREPROCESSOR -// Implemented unconditionally: -// N3911 void_t -// N4089 Safe Conversions In unique_ptr -// N4169 invoke() -// N4258 noexcept Cleanups -// N4259 uncaught_exceptions() -// N4277 Trivially Copyable reference_wrapper -// N4279 insert_or_assign()/try_emplace() For map/unordered_map -// N4280 size(), empty(), data() -// N4366 Precisely Constraining unique_ptr Assignment -// N4387 Improving pair And tuple -// N4389 bool_constant -// N4508 shared_mutex (Untimed) -// N4510 Supporting Incomplete Types In vector/list/forward_list -// P0006R0 Variable Templates For Type Traits (is_same_v, etc.) -// P0007R1 as_const() -// P0013R1 Logical Operator Type Traits (conjunction, etc.) -// P0033R1 Rewording enable_shared_from_this -// P0063R3 C11 Standard Library -// P0074R0 owner_less<> -// P0092R1 floor(), ceil(), round(), abs() -// P0340R3 SFINAE-Friendly underlying_type -// P0414R2 shared_ptr, shared_ptr -// P0418R2 atomic compare_exchange memory_order Requirements -// P0435R1 Overhauling common_type -// P0497R0 Fixing shared_ptr For Arrays -// P0513R0 Poisoning hash -// P0516R0 Marking shared_future Copying As noexcept -// P0517R0 Constructing future_error From future_errc -// P0548R1 Tweaking common_type And duration -// P0558R1 Resolving atomic Named Base Class Inconsistencies -// P0599R1 noexcept hash -// P0738R2 istream_iterator Cleanup -// P0771R1 noexcept For std::function's Move Constructor -// P0777R1 Avoiding Unnecessary decay -// P0809R0 Comparing Unordered Containers -// P0941R2 Feature-Test Macros -// P0972R0 noexcept For zero(), min(), max() -// P1164R1 Making create_directory() Intuitive -// P1902R1 Missing Feature-Test Macros 2017-2019 - -// _HAS_CXX17 directly controls: -// P0005R4 not_fn() -// P0024R2 Parallel Algorithms -// P0025R1 clamp() -// P0030R1 hypot(x, y, z) -// P0031R0 constexpr For (Again) And -// P0032R3 Homogeneous Interface For variant/any/optional -// P0040R3 Extending Memory Management Tools -// P0067R5 Elementary String Conversions -// P0083R3 Splicing Maps And Sets -// P0084R2 Emplace Return Type -// P0088R3 -// P0137R1 launder() -// P0152R1 atomic::is_always_lock_free -// P0154R1 hardware_destructive_interference_size, etc. -// P0156R2 scoped_lock -// P0163R0 shared_ptr::weak_type -// P0185R1 is_swappable, is_nothrow_swappable -// P0209R2 make_from_tuple() -// P0218R1 -// P0220R1 , , , , apply(), sample(), Boyer-Moore search() -// P0226R1 Mathematical Special Functions -// P0253R1 Fixing Searcher Return Types -// P0254R2 Integrating string_view And std::string -// P0258R2 has_unique_object_representations -// P0272R1 Non-const basic_string::data() -// P0295R0 gcd(), lcm() -// P0307R2 Making Optional Greater Equal Again -// P0336R1 Renaming Parallel Execution Policies -// P0337R0 Deleting polymorphic_allocator Assignment -// P0358R1 Fixes For not_fn() -// P0393R3 Making Variant Greater Equal -// P0394R4 Parallel Algorithms Should terminate() For Exceptions -// P0403R1 UDLs For ("meow"sv, etc.) -// P0426R1 constexpr For char_traits -// P0433R2 Deduction Guides For The STL -// P0452R1 Unifying Parallel Algorithms -// P0504R0 Revisiting in_place_t/in_place_type_t/in_place_index_t -// P0505R0 constexpr For (Again) -// P0508R0 Clarifying insert_return_type -// P0510R0 Rejecting variants Of Nothing, Arrays, References, And Incomplete Types -// P0602R4 Propagating Copy/Move Triviality In variant/optional -// P0604R0 invoke_result, is_invocable, is_nothrow_invocable -// P0607R0 Inline Variables For The STL -// P0682R1 Repairing Elementary String Conversions -// P0739R0 Improving Class Template Argument Deduction For The STL -// P0858R0 Constexpr Iterator Requirements - -// _HAS_CXX17 indirectly controls: -// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff -// P0003R5 Removing Dynamic Exception Specifications -// P0004R1 Removing Deprecated Iostreams Aliases -// P0298R3 std::byte -// P0302R1 Removing Allocator Support In std::function -// LWG-2385 function::assign allocator argument doesn't make sense -// LWG-2921 packaged_task and type-erased allocators -// LWG-2976 Dangling uses_allocator specialization for packaged_task -// The non-Standard std::tr1 namespace and TR1-only machinery -// Enforcement of matching allocator value_types - -// _HAS_CXX17 and _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS control: -// P0174R2 Deprecating Vestigial Library Parts -// P0521R0 Deprecating shared_ptr::unique() -// P0618R0 Deprecating -// Other C++17 deprecation warnings - -// _HAS_CXX20 directly controls: -// P0020R6 atomic, atomic, atomic -// P0318R1 unwrap_reference, unwrap_ref_decay -// P0325R4 to_array() -// P0356R5 bind_front() -// P0439R0 enum class memory_order -// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view -// P0458R2 contains() For Ordered And Unordered Associative Containers -// P0463R1 endian -// P0482R6 Library Support For char8_t -// (mbrtoc8 and c8rtomb not yet implemented) -// P0487R1 Fixing operator>>(basic_istream&, CharT*) -// P0550R2 remove_cvref -// P0553R4 Rotating And Counting Functions -// P0556R3 ispow2(), ceil2(), floor2(), log2p1() -// (log2p1() is called bit_length() as of D1956) -// P0595R2 is_constant_evaluated() -// P0616R0 Using move() In -// P0631R8 Math Constants -// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type -// P0653R2 to_address() -// P0655R1 visit() -// P0674R1 make_shared() For Arrays -// P0758R1 is_nothrow_convertible -// P0768R1 Library Support For The Spaceship Comparison Operator <=> -// (partially implemented) -// P0769R2 shift_left(), shift_right() -// P0811R3 midpoint(), lerp() -// (partially implemented, lerp() not yet constexpr) -// P0887R1 type_identity -// P0896R4 Ranges -// (partially implemented) -// P0898R3 Standard Library Concepts -// P0919R3 Heterogeneous Lookup For Unordered Containers -// P0966R1 string::reserve() Should Not Shrink -// P1209R0 erase_if(), erase() -// P1227R2 Signed std::ssize(), Unsigned span::size() -// (partially implemented) -// P1357R1 is_bounded_array, is_unbounded_array -// P1612R1 Relocating endian To -// P1651R0 bind_front() Should Not Unwrap reference_wrapper -// P1690R1 Refining Heterogeneous Lookup For Unordered Containers -// P1754R1 Rename Concepts To standard_case -// P????R? directory_entry::clear_cache() - -// _HAS_CXX20 and _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS control: -// P0767R1 Deprecating is_pod -// Other C++20 deprecation warnings - -// Parallel Algorithms Notes -// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. -// This implementation parallelizes several common algorithm calls, but not all. -// -// The following algorithms are parallelized. -// * adjacent_difference -// * adjacent_find -// * all_of -// * any_of -// * count -// * count_if -// * equal -// * exclusive_scan -// * find -// * find_end -// * find_first_of -// * find_if -// * find_if_not -// * for_each -// * for_each_n -// * inclusive_scan -// * is_heap -// * is_heap_until -// * is_partitioned -// * is_sorted -// * is_sorted_until -// * mismatch -// * none_of -// * partition -// * reduce -// * remove -// * remove_if -// * replace -// * replace_if -// * search -// * search_n -// * set_difference -// * set_intersection -// * sort -// * stable_sort -// * transform -// * transform_exclusive_scan -// * transform_inclusive_scan -// * transform_reduce -// -// The following are not presently parallelized: -// -// No apparent parallelism performance improvement on target hardware; all algorithms which -// merely copy or permute elements with no branches are typically memory bandwidth limited. -// * copy -// * copy_n -// * fill -// * fill_n -// * move -// * reverse -// * reverse_copy -// * rotate -// * rotate_copy -// * shift_left -// * shift_right -// * swap_ranges -// -// Confusion over user parallelism requirements exists; likely in the above category anyway. -// * generate -// * generate_n -// -// Effective parallelism suspected to be infeasible. -// * partial_sort -// * partial_sort_copy -// -// Not yet evaluated; parallelism may be implemented in a future release and is suspected to be beneficial. -// * copy_if -// * includes -// * inplace_merge -// * lexicographical_compare -// * max_element -// * merge -// * min_element -// * minmax_element -// * nth_element -// * partition_copy -// * remove_copy -// * remove_copy_if -// * replace_copy -// * replace_copy_if -// * set_symmetric_difference -// * set_union -// * stable_partition -// * unique -// * unique_copy - -#include -#include // The _HAS_CXX tags must be defined before including this. - -#ifndef _STL_WARNING_LEVEL -#if defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#define _STL_WARNING_LEVEL 4 -#else // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#define _STL_WARNING_LEVEL 3 -#endif // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#endif // _STL_WARNING_LEVEL - -#if _STL_WARNING_LEVEL < 3 -#error _STL_WARNING_LEVEL cannot be less than 3. -#endif // _STL_WARNING_LEVEL < 3 - -#if _STL_WARNING_LEVEL > 4 -#error _STL_WARNING_LEVEL cannot be greater than 4. -#endif // _STL_WARNING_LEVEL > 4 - -// _HAS_NODISCARD (in vcruntime.h) controls: -// [[nodiscard]] attributes on STL functions - -// Controls whether the STL uses "if constexpr" internally -#ifndef _HAS_IF_CONSTEXPR -#ifdef __CUDACC__ -#define _HAS_IF_CONSTEXPR 0 -#else // __CUDACC__ -#define _HAS_IF_CONSTEXPR 1 -#endif // __CUDACC__ -#endif // _HAS_IF_CONSTEXPR - -// Controls whether the STL uses "conditional explicit" internally -#ifndef _HAS_CONDITIONAL_EXPLICIT -#ifdef __cpp_conditional_explicit -#define _HAS_CONDITIONAL_EXPLICIT 1 -#elif defined(__CUDACC__) -#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION -#elif defined(__clang__) -#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION, LLVM-42694 -#else // vvv C1XX or non-CUDA EDG vvv -#define _HAS_CONDITIONAL_EXPLICIT 1 -#endif // ^^^ C1XX or non-CUDA EDG ^^^ -#endif // _HAS_CONDITIONAL_EXPLICIT - -// warning C4577: 'noexcept' used with no exception handling mode specified; -// termination on exception is not guaranteed. Specify /EHsc (/Wall) -#if _HAS_EXCEPTIONS -#define _STL_DISABLED_WARNING_C4577 -#else // _HAS_EXCEPTIONS -#define _STL_DISABLED_WARNING_C4577 4577 -#endif // _HAS_EXCEPTIONS - -// warning C4984: 'if constexpr' is a C++17 language extension -#if !_HAS_CXX17 && _HAS_IF_CONSTEXPR -#define _STL_DISABLED_WARNING_C4984 4984 -#else // !_HAS_CXX17 && _HAS_IF_CONSTEXPR -#define _STL_DISABLED_WARNING_C4984 -#endif // !_HAS_CXX17 && _HAS_IF_CONSTEXPR - -// warning C5053: support for 'explicit()' in C++17 and earlier is a vendor extension -#if !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT -#define _STL_DISABLED_WARNING_C5053 5053 -#else // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT -#define _STL_DISABLED_WARNING_C5053 -#endif // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT - -#ifndef _STL_EXTRA_DISABLED_WARNINGS -#define _STL_EXTRA_DISABLED_WARNINGS -#endif // _STL_EXTRA_DISABLED_WARNINGS - -// warning C4180: qualifier applied to function type has no meaning; ignored -// warning C4412: function signature contains type 'meow'; C++ objects are unsafe to pass between pure code -// and mixed or native. (/Wall) -// warning C4455: literal suffix identifiers that do not start with an underscore are reserved -// warning C4472: 'meow' is a native enum: add an access specifier (private/public) -// to declare a managed enum (/Wall) -// warning C4494: Ignoring __declspec(allocator) because the function return type is not a pointer or reference -// warning C4514: unreferenced inline function has been removed (/Wall) -// warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; -// structured exceptions (SEH) are no longer caught (/Wall) -// warning C4574: 'MACRO' is defined to be '0': did you mean to use '#if MACRO'? (/Wall) -// warning C4582: 'union': constructor is not implicitly called (/Wall) -// warning C4583: 'union': destructor is not implicitly called (/Wall) -// warning C4587: behavior change: constructor is no longer implicitly called (/Wall) -// warning C4588: behavior change: destructor is no longer implicitly called (/Wall) -// warning C4619: #pragma warning: there is no warning number 'number' (/Wall) -// warning C4623: default constructor was implicitly defined as deleted (/Wall) -// warning C4625: copy constructor was implicitly defined as deleted (/Wall) -// warning C4626: assignment operator was implicitly defined as deleted (/Wall) -// warning C4643: Forward declaring 'meow' in namespace std is not permitted by the C++ Standard. (/Wall) -// warning C4702: unreachable code -// warning C4793: function compiled as native -// warning C4820: 'N' bytes padding added after data member 'meow' (/Wall) -// warning C4988: variable declared outside class/function scope (/Wall /d1WarnOnGlobals) -// warning C5026: move constructor was implicitly defined as deleted (/Wall) -// warning C5027: move assignment operator was implicitly defined as deleted (/Wall) -// warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified (/Wall) - -#ifndef _STL_DISABLED_WARNINGS -// clang-format off -#define _STL_DISABLED_WARNINGS \ - 4180 4412 4455 4472 4494 4514 4571 4574 4582 4583 \ - 4587 4588 4619 4623 4625 4626 4643 4702 4793 4820 \ - 4988 5026 5027 5045 \ - _STL_DISABLED_WARNING_C4577 \ - _STL_DISABLED_WARNING_C4984 \ - _STL_DISABLED_WARNING_C5053 \ - _STL_EXTRA_DISABLED_WARNINGS -// clang-format on -#endif // _STL_DISABLED_WARNINGS - -// warning: constexpr if is a C++17 extension [-Wc++17-extensions] -// warning: user-defined literal suffixes not starting with '_' are reserved [-Wuser-defined-literals] -// warning: unknown pragma ignored [-Wunknown-pragmas] -#ifndef _STL_DISABLE_CLANG_WARNINGS -#ifdef __clang__ -// clang-format off -#define _STL_DISABLE_CLANG_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wuser-defined-literals\"") \ - _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -// clang-format on -#else // __clang__ -#define _STL_DISABLE_CLANG_WARNINGS -#endif // __clang__ -#endif // _STL_DISABLE_CLANG_WARNINGS - -#ifndef _STL_RESTORE_CLANG_WARNINGS -#ifdef __clang__ -#define _STL_RESTORE_CLANG_WARNINGS _Pragma("clang diagnostic pop") -#else // __clang__ -#define _STL_RESTORE_CLANG_WARNINGS -#endif // __clang__ -#endif // _STL_RESTORE_CLANG_WARNINGS - -// clang-format off -#ifndef _STL_DISABLE_DEPRECATED_WARNING -#ifdef __clang__ -#define _STL_DISABLE_DEPRECATED_WARNING \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#else // __clang__ -#define _STL_DISABLE_DEPRECATED_WARNING \ - __pragma(warning(push)) \ - __pragma(warning(disable : 4996)) // was declared deprecated -#endif // __clang__ -#endif // _STL_DISABLE_DEPRECATED_WARNING -// clang-format on - -#ifndef _STL_RESTORE_DEPRECATED_WARNING -#ifdef __clang__ -#define _STL_RESTORE_DEPRECATED_WARNING _Pragma("clang diagnostic pop") -#else // __clang__ -#define _STL_RESTORE_DEPRECATED_WARNING __pragma(warning(pop)) -#endif // __clang__ -#endif // _STL_RESTORE_DEPRECATED_WARNING - -#define _CPPLIB_VER 650 -#define _MSVC_STL_VERSION 142 -#define _MSVC_STL_UPDATE 201911L - -#ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH -#ifdef __EDG__ -// not attempting to detect __EDG_VERSION__ being less than expected -#elif defined(__clang__) -#if __clang_major__ < 9 -#error STL1000: Unexpected compiler version, expected Clang 9.0.0 or newer. -#endif // ^^^ old Clang ^^^ -#elif defined(_MSC_VER) -#if _MSC_VER < 1924 // Coarse-grained, not inspecting _MSC_FULL_VER -#error STL1001: Unexpected compiler version, expected MSVC 19.24 or newer. -#endif // ^^^ old MSVC ^^^ -#else // vvv other compilers vvv -// not attempting to detect other compilers -#endif // ^^^ other compilers ^^^ -#endif // _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH - -#ifndef _HAS_STATIC_RTTI -#define _HAS_STATIC_RTTI 1 -#endif // _HAS_STATIC_RTTI - -#if defined(_CPPRTTI) && !_HAS_STATIC_RTTI -#error /GR implies _HAS_STATIC_RTTI. -#endif // defined(_CPPRTTI) && !_HAS_STATIC_RTTI - -// C++17 constexpr additions -#if _HAS_CXX17 -#define _CONSTEXPR17 constexpr -#else // ^^^ has C++17 constexpr additions / no C++17 constexpr additions vvv -#define _CONSTEXPR17 inline -#endif // _HAS_CXX17 - -// P0607R0 Inline Variables For The STL -#if _HAS_CXX17 -#define _INLINE_VAR inline -#else // _HAS_CXX17 -#define _INLINE_VAR -#endif // _HAS_CXX17 - -// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff -#ifndef _HAS_AUTO_PTR_ETC -#define _HAS_AUTO_PTR_ETC (!_HAS_CXX17) -#endif // _HAS_AUTO_PTR_ETC - -// P0003R5 Removing Dynamic Exception Specifications -#ifndef _HAS_UNEXPECTED -#define _HAS_UNEXPECTED (!_HAS_CXX17) -#endif // _HAS_UNEXPECTED - -// P0004R1 Removing Deprecated Iostreams Aliases -#ifndef _HAS_OLD_IOSTREAMS_MEMBERS -#define _HAS_OLD_IOSTREAMS_MEMBERS (!_HAS_CXX17) -#endif // _HAS_OLD_IOSTREAMS_MEMBERS - -// P0298R3 std::byte -#ifndef _HAS_STD_BYTE -#define _HAS_STD_BYTE _HAS_CXX17 // inspected by GSL, do not remove -#endif // _HAS_STD_BYTE - -// P0302R1 Removing Allocator Support In std::function -// LWG-2385 function::assign allocator argument doesn't make sense -// LWG-2921 packaged_task and type-erased allocators -// LWG-2976 Dangling uses_allocator specialization for packaged_task -#ifndef _HAS_FUNCTION_ALLOCATOR_SUPPORT -#define _HAS_FUNCTION_ALLOCATOR_SUPPORT (!_HAS_CXX17) -#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT - -// The non-Standard std::tr1 namespace and TR1-only machinery -#ifndef _HAS_TR1_NAMESPACE -#define _HAS_TR1_NAMESPACE (!_HAS_CXX17) -#endif // _HAS_TR1_NAMESPACE - -// STL4000 is "_STATIC_CPPLIB is deprecated", currently in yvals.h -// STL4001 is "/clr:pure is deprecated", currently in yvals.h - -#if _HAS_TR1_NAMESPACE -#ifdef _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -#define _DEPRECATE_TR1_NAMESPACE -#else // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -#define _DEPRECATE_TR1_NAMESPACE \ - [[deprecated( \ - "warning STL4002: " \ - "The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED. You can " \ - "define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING to acknowledge that you have received this warning.")]] -#endif // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -#endif // _HAS_TR1_NAMESPACE - -// STL4003 was "The non-Standard std::identity struct is deprecated and will be REMOVED." - -// Enforcement of matching allocator value_types -#ifndef _ENFORCE_MATCHING_ALLOCATORS -#define _ENFORCE_MATCHING_ALLOCATORS _HAS_CXX17 -#endif // _ENFORCE_MATCHING_ALLOCATORS - -#define _MISMATCHED_ALLOCATOR_MESSAGE(_CONTAINER, _VALUE_TYPE) \ - _CONTAINER " requires that Allocator's value_type match " _VALUE_TYPE \ - " (See N4659 26.2.1 [container.requirements.general]/16 allocator_type)" \ - " Either fix the allocator value_type or define _ENFORCE_MATCHING_ALLOCATORS=0" \ - " to suppress this diagnostic." - -// Enforcement of Standard facet specializations -#ifndef _ENFORCE_FACET_SPECIALIZATIONS -#define _ENFORCE_FACET_SPECIALIZATIONS 0 -#endif // _ENFORCE_FACET_SPECIALIZATIONS - -#define _FACET_SPECIALIZATION_MESSAGE \ - "Unsupported facet specialization; see N4800 27.3.1.1.1 [locale.category]. " \ - "Either use a Standard specialization or define _ENFORCE_FACET_SPECIALIZATIONS=0 " \ - "to suppress this diagnostic." - -// To improve compiler throughput, use 'hidden friend' operators in instead of non-members that are -// depicted in the Standard. -#ifndef _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS -#define _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS 1 -#endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS - -#if _HAS_IF_CONSTEXPR -#define _CONSTEXPR_IF constexpr -#else // _HAS_IF_CONSTEXPR -#define _CONSTEXPR_IF -#endif // _HAS_IF_CONSTEXPR - -#ifdef __clang__ -#define _CONSTEVAL consteval -#else // ^^^ supports consteval / no consteval vvv -#define _CONSTEVAL constexpr -#endif // ^^^ no consteval ^^^ - -// Controls whether the STL will force /fp:fast to enable vectorization of algorithms defined -// in the standard as special cases; such as reduce, transform_reduce, inclusive_scan, exclusive_scan -#ifndef _STD_VECTORIZE_WITH_FLOAT_CONTROL -#ifdef _M_FP_EXCEPT -#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 0 -#else // ^^^ floating point exceptions enabled / floating point exceptions disabled (default) vvv -#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 1 -#endif // _M_FP_EXCEPT -#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL - -// P0174R2 Deprecating Vestigial Library Parts -// P0521R0 Deprecating shared_ptr::unique() -// Other C++17 deprecation warnings - -// N4659 D.4 [depr.cpp.headers] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_C_HEADER \ - [[deprecated("warning STL4004: " \ - ", , , and are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_C_HEADER -#endif // ^^^ warning disabled ^^^ - -// N4659 D.6 [depr.str.strstreams] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_STRSTREAM \ - [[deprecated("warning STL4005: is deprecated in C++17. " \ - "You can define _SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_STRSTREAM -#endif // ^^^ warning disabled ^^^ - -// N4659 D.7 [depr.uncaught] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION \ - [[deprecated("warning STL4006: " \ - "std::uncaught_exception() is deprecated in C++17. " \ - "It is superseded by std::uncaught_exceptions(), plural. " \ - "You can define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION -#endif // ^^^ warning disabled ^^^ - -// N4659 D.8.1 [depr.weak.result_type] -// N4659 D.8.2 [depr.func.adaptor.typedefs] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS \ - [[deprecated( \ - "warning STL4007: Many result_type typedefs " \ - "and all argument_type, first_argument_type, and second_argument_type typedefs are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS -#endif // ^^^ warning disabled ^^^ - -// N4659 D.8.3 [depr.negators] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_NEGATORS \ - [[deprecated("warning STL4008: " \ - "std::not1(), std::not2(), std::unary_negate, and std::binary_negate are deprecated in C++17. " \ - "They are superseded by std::not_fn(). " \ - "You can define _SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_NEGATORS -#endif // ^^^ warning disabled ^^^ - -// STL4009 was "std::allocator is deprecated in C++17" - -// N4659 D.9 [depr.default.allocator] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS \ - [[deprecated("warning STL4010: " \ - "Various members of std::allocator are deprecated in C++17. " \ - "Use std::allocator_traits instead of accessing these members directly. " \ - "You can define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS -#endif // ^^^ warning disabled ^^^ - -// N4659 D.10 [depr.storage.iterator] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR \ - [[deprecated("warning STL4011: " \ - "std::raw_storage_iterator is deprecated in C++17. " \ - "Consider using the std::uninitialized_copy() family of algorithms instead. " \ - "You can define _SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR -#endif // ^^^ warning disabled ^^^ - -// N4659 D.11 [depr.temporary.buffer] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_TEMPORARY_BUFFER \ - [[deprecated("warning STL4012: " \ - "std::get_temporary_buffer() and std::return_temporary_buffer() are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_TEMPORARY_BUFFER -#endif // ^^^ warning disabled ^^^ - -// N4659 D.12 [depr.meta.types] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_IS_LITERAL_TYPE \ - [[deprecated("warning STL4013: " \ - "std::is_literal_type and std::is_literal_type_v are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_IS_LITERAL_TYPE -#endif // ^^^ warning disabled ^^^ - -// N4659 D.12 [depr.meta.types] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_RESULT_OF \ - [[deprecated("warning STL4014: " \ - "std::result_of and std::result_of_t are deprecated in C++17. " \ - "They are superseded by std::invoke_result and std::invoke_result_t. " \ - "You can define _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_RESULT_OF -#endif // ^^^ warning disabled ^^^ - -// N4659 D.13 [depr.iterator.primitives] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS \ - [[deprecated( \ - "warning STL4015: " \ - "The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. " \ - "(The header is NOT deprecated.) The C++ Standard has never required user-defined iterators to " \ - "derive from std::iterator. To fix this warning, stop deriving from std::iterator and start providing " \ - "publicly accessible typedefs named iterator_category, value_type, difference_type, pointer, and reference. " \ - "Note that value_type is required to be non-const, even for constant iterators. " \ - "You can define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS -#endif // ^^^ warning disabled ^^^ - -// N4659 D.14 [depr.util.smartptr.shared.obs] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE \ - [[deprecated("warning STL4016: " \ - "std::shared_ptr::unique() is deprecated in C++17. " \ - "You can define _SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE -#endif // ^^^ warning disabled ^^^ - -// N4659 D.15 [depr.locale.stdcvt] -// N4659 D.16 [depr.conversions] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_CODECVT_HEADER \ - [[deprecated( \ - "warning STL4017: " \ - "std::wbuffer_convert, std::wstring_convert, and the header (containing std::codecvt_mode, " \ - "std::codecvt_utf8, std::codecvt_utf16, and std::codecvt_utf8_utf16) are deprecated in C++17. " \ - "(The std::codecvt class template is NOT deprecated.) " \ - "The C++ Standard doesn't provide equivalent non-deprecated functionality; " \ - "consider using MultiByteToWideChar() and WideCharToMultiByte() from instead. " \ - "You can define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_CODECVT_HEADER -#endif // ^^^ warning disabled ^^^ - -// STL4018 was "The non-Standard std::tr2::sys namespace is deprecated and will be REMOVED." - -#ifdef _SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING -#define _DEPRECATE_FPOS_SEEKPOS -#else // ^^^ warning disabled / warning enabled vvv -#define _DEPRECATE_FPOS_SEEKPOS \ - [[deprecated("warning STL4019: " \ - "The member std::fpos::seekpos() is non-Standard, and is preserved only for compatibility with " \ - "workarounds for old versions of Visual C++. It will be removed in a future release, and in this " \ - "release always returns 0. Please use standards-conforming mechanisms to manipulate fpos, such as " \ - "conversions to and from streamoff, or an integral type, instead. If you are receiving this message " \ - "while compiling Boost.IOStreams, a fix has been submitted upstream to make Boost use " \ - "standards-conforming mechanisms, as it does for other compilers. You can define " \ - "_SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING to acknowledge that you have received this warning, " \ - "or define _REMOVE_FPOS_SEEKPOS to remove std::fpos::seekpos entirely.")]] -#endif // ^^^ warning enabled ^^^ - -// P0482R6 Library Support For char8_t -// Other C++20 deprecation warnings - -// N4810 D.16 [depr.locale.category] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_CODECVT_FACETS \ - [[deprecated("warning STL4020: " \ - "std::codecvt, std::codecvt, " \ - "std::codecvt_byname, and std::codecvt_byname " \ - "are deprecated in C++20 and replaced by specializations with a second argument of type char8_t. " \ - "You can define _SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_CODECVT_FACETS -#endif // ^^^ warning disabled ^^^ - -// N4810 D.17 [depr.fs.path.factory] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_U8PATH_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_U8PATH \ - [[deprecated("warning STL4021: " \ - "The std::filesystem::u8path() overloads are deprecated in C++20. " \ - "The constructors of std::filesystem::path provide equivalent functionality via construction from " \ - "u8string, u8string_view, or iterators with value_type char8_t." \ - "You can define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_U8PATH -#endif // ^^^ warning disabled ^^^ - -#if !defined(_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING) -#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND \ - [[deprecated( \ - "warning STL4022: " \ - "The hash_meow and unordered_meow containers' non-Standard lower_bound() member was provided for interface " \ - "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ - "hash_meow or unordered_meow containers. Please use the find() member instead. You can define " \ - "_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND -#endif // ^^^ warning disabled ^^^ - -#if !defined(_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING) -#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND \ - [[deprecated( \ - "warning STL4023: " \ - "The hash_meow and unordered_meow containers' non-Standard upper_bound() member was provided for interface " \ - "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ - "hash_meow or unordered_meow containers. Please use the second iterator returned by the " \ - "equal_range() member instead. You can define " \ - "_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND -#endif // ^^^ warning disabled ^^^ - -// P0966R1 [depr.string.capacity] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT \ - [[deprecated("warning STL4024: " \ - "std::string::reserve() without an argument is deprecated in C++20. " \ - "To shrink the string's capacity, use std::string::shrink_to_fit() instead. Otherwise, provide an " \ - "argument to std::string::reserve(). " \ - "You can define _SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT -#endif // ^^^ warning disabled ^^^ - -// P0767R1 [depr.meta.types] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_IS_POD_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_IS_POD \ - [[deprecated("warning STL4025: " \ - "std::is_pod and std::is_pod_v are deprecated in C++20. " \ - "The std::is_trivially_copyable and/or std::is_standard_layout traits likely suit your use case. " \ - "You can define _SILENCE_CXX20_IS_POD_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_IS_POD -#endif // ^^^ warning disabled ^^^ - -#if _HAS_CXX20 && !defined(_SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING) -#define _DEPRECATE_EXPERIMENTAL_ERASE \ - [[deprecated("warning STL4026: " \ - "std::experimental::erase() and std::experimental::erase_if() are deprecated by Microsoft and will " \ - "be REMOVED. They are superseded by std::erase() and std::erase_if(). " \ - "You can define _SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING to acknowledge that you have " \ - "received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _DEPRECATE_EXPERIMENTAL_ERASE -#endif // ^^^ warning disabled ^^^ - -// next warning number: STL4027 - - -// LIBRARY FEATURE-TEST MACROS - -// C++14 -#define __cpp_lib_chrono_udls 201304L -#define __cpp_lib_complex_udls 201309L -#define __cpp_lib_exchange_function 201304L -#define __cpp_lib_generic_associative_lookup 201304L -#define __cpp_lib_integer_sequence 201304L -#define __cpp_lib_integral_constant_callable 201304L -#define __cpp_lib_is_final 201402L -#define __cpp_lib_is_null_pointer 201309L -#define __cpp_lib_make_reverse_iterator 201402L -#define __cpp_lib_make_unique 201304L -#define __cpp_lib_null_iterators 201304L -#define __cpp_lib_quoted_string_io 201304L -#define __cpp_lib_result_of_sfinae 201210L -#define __cpp_lib_robust_nonmodifying_seq_ops 201304L -#ifndef _M_CEE -#define __cpp_lib_shared_timed_mutex 201402L -#endif // _M_CEE -#define __cpp_lib_string_udls 201304L -#define __cpp_lib_transformation_trait_aliases 201304L -#define __cpp_lib_tuple_element_t 201402L -#define __cpp_lib_tuples_by_type 201304L - -// C++17 -#define __cpp_lib_addressof_constexpr 201603L -#define __cpp_lib_allocator_traits_is_always_equal 201411L -#define __cpp_lib_as_const 201510L -#define __cpp_lib_bool_constant 201505L -#define __cpp_lib_enable_shared_from_this 201603L -#define __cpp_lib_incomplete_container_elements 201505L -#define __cpp_lib_invoke 201411L -#define __cpp_lib_logical_traits 201510L -#define __cpp_lib_map_try_emplace 201411L -#define __cpp_lib_nonmember_container_access 201411L -#ifndef _USING_V110_SDK71_ -#define __cpp_lib_shared_mutex 201505L -#endif // _USING_V110_SDK71_ -#define __cpp_lib_shared_ptr_arrays 201707L -#define __cpp_lib_transparent_operators 201510L -#define __cpp_lib_type_trait_variable_templates 201510L -#define __cpp_lib_uncaught_exceptions 201411L -#define __cpp_lib_unordered_map_try_emplace 201411L -#define __cpp_lib_void_t 201411L - -#if _HAS_CXX17 -#define __cpp_lib_any 201606L -#define __cpp_lib_apply 201603L -#define __cpp_lib_array_constexpr 201803L -#define __cpp_lib_atomic_is_always_lock_free 201603L -#define __cpp_lib_boyer_moore_searcher 201603L -#if _HAS_STD_BYTE -#define __cpp_lib_byte 201603L -#endif // _HAS_STD_BYTE -#define __cpp_lib_chrono 201611L -#define __cpp_lib_clamp 201603L -#ifndef _M_CEE -#define __cpp_lib_execution 201603L -#endif // _M_CEE -#define __cpp_lib_filesystem 201703L -#define __cpp_lib_gcd_lcm 201606L -#define __cpp_lib_hardware_interference_size 201703L -#define __cpp_lib_has_unique_object_representations 201606L -#define __cpp_lib_hypot 201603L -#define __cpp_lib_is_aggregate 201703L -#define __cpp_lib_is_invocable 201703L -#define __cpp_lib_is_swappable 201603L -#define __cpp_lib_launder 201606L -#define __cpp_lib_make_from_tuple 201606L -#define __cpp_lib_math_special_functions 201603L -#define __cpp_lib_memory_resource 201603L -#define __cpp_lib_node_extract 201606L -#define __cpp_lib_not_fn 201603L -#define __cpp_lib_optional 201606L -#ifndef _M_CEE -#define __cpp_lib_parallel_algorithm 201603L -#endif // _M_CEE -#define __cpp_lib_raw_memory_algorithms 201606L -#define __cpp_lib_sample 201603L -#define __cpp_lib_scoped_lock 201703L -#define __cpp_lib_shared_ptr_weak_type 201606L -#define __cpp_lib_string_view 201803L -#define __cpp_lib_to_chars 201611L -#define __cpp_lib_variant 201606L -#else // _HAS_CXX17 -#define __cpp_lib_chrono 201510L -#endif // _HAS_CXX17 - -// C++20 -#if _HAS_CXX20 -#define __cpp_lib_atomic_float 201711L -#define __cpp_lib_bind_front 201907L - -#if defined(__clang__) || defined(__EDG__) -#define __cpp_lib_bitops 201907L -#else // ^^^ Clang and EDG / MSVC vvv -// a future MSVC update will embed CPU feature detection into intrinsics -// TRANSITION, VSO-1020212 -#endif // defined(__clang__) || defined(__EDG__) - -#define __cpp_lib_bounded_array_traits 201902L - -#ifdef __cpp_char8_t -#define __cpp_lib_char8_t 201811L -#endif // __cpp_char8_t - -#if defined(__cpp_concepts) && __cpp_concepts > 201507L -#define __cpp_lib_concepts 201907L - -// P0898R3 (as modified by P1754R1) std::boolean -#ifndef _HAS_STD_BOOLEAN -#define _HAS_STD_BOOLEAN 1 -#endif // _HAS_STD_BOOLEAN -#endif // defined(__cpp_concepts) && __cpp_concepts > 201507L - -#define __cpp_lib_endian 201907L -#define __cpp_lib_erase_if 201811L -#define __cpp_lib_generic_unordered_lookup 201811L -#define __cpp_lib_int_pow2 201806L - -#if defined(__clang__) || defined(__EDG__) \ - || (defined(_MSC_VER) && _MSC_VER >= 1925 && !(_MSC_FULL_VER == 192528318 && _MSC_BUILD == 97)) -#define __cpp_lib_is_constant_evaluated 201811L -#endif // TRANSITION, VS 2019 16.5 Preview 2 and toolset update - -#define __cpp_lib_list_remove_return_type 201806L -#define __cpp_lib_math_constants 201907L -#define __cpp_lib_nothrow_convertible 201806L -#define __cpp_lib_remove_cvref 201711L -#define __cpp_lib_shift 201806L -#define __cpp_lib_ssize 201902L -#define __cpp_lib_starts_ends_with 201711L -#define __cpp_lib_to_address 201711L -#define __cpp_lib_to_array 201907L -#define __cpp_lib_type_identity 201806L -#define __cpp_lib_unwrap_ref 201811L -#endif // _HAS_CXX20 - -// EXPERIMENTAL -#define __cpp_lib_experimental_erase_if 201411L -#define __cpp_lib_experimental_filesystem 201406L - - -#ifdef _RTC_CONVERSION_CHECKS_ENABLED -#ifndef _ALLOW_RTCc_IN_STL -#error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ -compiler option, or define _ALLOW_RTCc_IN_STL to acknowledge that you have received this warning. -#endif // _ALLOW_RTCc_IN_STL -#endif // _RTC_CONVERSION_CHECKS_ENABLED - -#ifndef _DECLSPEC_ALLOCATOR -#ifdef __clang__ -#define _DECLSPEC_ALLOCATOR -#else // ^^^ Clang / non-Clang vvv -#define _DECLSPEC_ALLOCATOR __declspec(allocator) -#endif // ^^^ non-Clang ^^^ -#endif // _DECLSPEC_ALLOCATOR - -#define _STRINGIZEX(x) #x -#define _STRINGIZE(x) _STRINGIZEX(x) -#define _EMPTY_ARGUMENT // for empty macro argument - -// NAMESPACE -#define _STD_BEGIN namespace std { -#define _STD_END } -#define _STD ::std:: -#define _RANGES ::std::ranges:: - -// We use the stdext (standard extension) namespace to contain extensions that are not part of the current standard -#define _STDEXT_BEGIN namespace stdext { -#define _STDEXT_END } -#define _STDEXT ::stdext:: - -#ifdef __cplusplus -#define _CSTD :: - -#define _EXTERN_C extern "C" { -#define _END_EXTERN_C } -#else // ^^^ __cplusplus / !__cplusplus vvv -#define _CSTD - -#define _EXTERN_C -#define _END_EXTERN_C -#endif // __cplusplus - -#ifdef _M_CEE_PURE -#define _EXTERN_C_UNLESS_PURE -#define _END_EXTERN_C_UNLESS_PURE -#define _STATIC_UNLESS_PURE // Avoid warning C4640: construction of local static object is not thread-safe (/Wall) -#else // ^^^ _M_CEE_PURE / !_M_CEE_PURE vvv -#define _EXTERN_C_UNLESS_PURE _EXTERN_C -#define _END_EXTERN_C_UNLESS_PURE _END_EXTERN_C -#define _STATIC_UNLESS_PURE static -#endif // _M_CEE_PURE - -#if defined(MRTDLL) && !defined(_CRTBLD) -#error In yvals_core.h, defined(MRTDLL) implies defined(_CRTBLD); !defined(_CRTBLD) implies !defined(MRTDLL) -#endif // defined(MRTDLL) && !defined(_CRTBLD) - -#if defined(MRTDLL) && !defined(_M_CEE_PURE) -#error In yvals_core.h, defined(MRTDLL) implies defined(_M_CEE_PURE); !defined(_M_CEE_PURE) implies !defined(MRTDLL) -#endif // defined(MRTDLL) && !defined(_M_CEE_PURE) - -#endif // _STL_COMPILER_PREPROCESSOR -#endif // _YVALS_CORE_H_ +// yvals_core.h internal header (core) + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _YVALS_CORE_H_ +#define _YVALS_CORE_H_ +#ifndef _STL_COMPILER_PREPROCESSOR +// All STL headers avoid exposing their contents when included by various +// non-C++-compiler tools to avoid breaking builds when we use newer language +// features in the headers than such tools understand. +#if defined(RC_INVOKED) || defined(Q_MOC_RUN) || defined(__midl) +#define _STL_COMPILER_PREPROCESSOR 0 +#else +#define _STL_COMPILER_PREPROCESSOR 1 +#endif +#endif // _STL_COMPILER_PREPROCESSOR + +#if _STL_COMPILER_PREPROCESSOR +// Implemented unconditionally: +// N3911 void_t +// N4089 Safe Conversions In unique_ptr +// N4169 invoke() +// N4258 noexcept Cleanups +// N4259 uncaught_exceptions() +// N4277 Trivially Copyable reference_wrapper +// N4279 insert_or_assign()/try_emplace() For map/unordered_map +// N4280 size(), empty(), data() +// N4366 Precisely Constraining unique_ptr Assignment +// N4387 Improving pair And tuple +// N4389 bool_constant +// N4508 shared_mutex (Untimed) +// N4510 Supporting Incomplete Types In vector/list/forward_list +// P0006R0 Variable Templates For Type Traits (is_same_v, etc.) +// P0007R1 as_const() +// P0013R1 Logical Operator Type Traits (conjunction, etc.) +// P0033R1 Rewording enable_shared_from_this +// P0063R3 C11 Standard Library +// P0074R0 owner_less<> +// P0092R1 floor(), ceil(), round(), abs() +// P0340R3 SFINAE-Friendly underlying_type +// P0414R2 shared_ptr, shared_ptr +// P0418R2 atomic compare_exchange memory_order Requirements +// P0435R1 Overhauling common_type +// P0497R0 Fixing shared_ptr For Arrays +// P0513R0 Poisoning hash +// P0516R0 Marking shared_future Copying As noexcept +// P0517R0 Constructing future_error From future_errc +// P0548R1 Tweaking common_type And duration +// P0558R1 Resolving atomic Named Base Class Inconsistencies +// P0599R1 noexcept hash +// P0738R2 istream_iterator Cleanup +// P0771R1 noexcept For std::function's Move Constructor +// P0777R1 Avoiding Unnecessary decay +// P0809R0 Comparing Unordered Containers +// P0941R2 Feature-Test Macros +// P0972R0 noexcept For zero(), min(), max() +// P1164R1 Making create_directory() Intuitive +// P1902R1 Missing Feature-Test Macros 2017-2019 + +// _HAS_CXX17 directly controls: +// P0005R4 not_fn() +// P0024R2 Parallel Algorithms +// P0025R1 clamp() +// P0030R1 hypot(x, y, z) +// P0031R0 constexpr For (Again) And +// P0032R3 Homogeneous Interface For variant/any/optional +// P0040R3 Extending Memory Management Tools +// P0067R5 Elementary String Conversions +// P0083R3 Splicing Maps And Sets +// P0084R2 Emplace Return Type +// P0088R3 +// P0137R1 launder() +// P0152R1 atomic::is_always_lock_free +// P0154R1 hardware_destructive_interference_size, etc. +// P0156R2 scoped_lock +// P0163R0 shared_ptr::weak_type +// P0185R1 is_swappable, is_nothrow_swappable +// P0209R2 make_from_tuple() +// P0218R1 +// P0220R1 , , , , apply(), sample(), Boyer-Moore search() +// P0226R1 Mathematical Special Functions +// P0253R1 Fixing Searcher Return Types +// P0254R2 Integrating string_view And std::string +// P0258R2 has_unique_object_representations +// P0272R1 Non-const basic_string::data() +// P0295R0 gcd(), lcm() +// P0307R2 Making Optional Greater Equal Again +// P0336R1 Renaming Parallel Execution Policies +// P0337R0 Deleting polymorphic_allocator Assignment +// P0358R1 Fixes For not_fn() +// P0393R3 Making Variant Greater Equal +// P0394R4 Parallel Algorithms Should terminate() For Exceptions +// P0403R1 UDLs For ("meow"sv, etc.) +// P0426R1 constexpr For char_traits +// P0433R2 Deduction Guides For The STL +// P0452R1 Unifying Parallel Algorithms +// P0504R0 Revisiting in_place_t/in_place_type_t/in_place_index_t +// P0505R0 constexpr For (Again) +// P0508R0 Clarifying insert_return_type +// P0510R0 Rejecting variants Of Nothing, Arrays, References, And Incomplete Types +// P0602R4 Propagating Copy/Move Triviality In variant/optional +// P0604R0 invoke_result, is_invocable, is_nothrow_invocable +// P0607R0 Inline Variables For The STL +// P0682R1 Repairing Elementary String Conversions +// P0739R0 Improving Class Template Argument Deduction For The STL +// P0858R0 Constexpr Iterator Requirements + +// _HAS_CXX17 indirectly controls: +// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff +// P0003R5 Removing Dynamic Exception Specifications +// P0004R1 Removing Deprecated Iostreams Aliases +// P0298R3 std::byte +// P0302R1 Removing Allocator Support In std::function +// LWG-2385 function::assign allocator argument doesn't make sense +// LWG-2921 packaged_task and type-erased allocators +// LWG-2976 Dangling uses_allocator specialization for packaged_task +// The non-Standard std::tr1 namespace and TR1-only machinery +// Enforcement of matching allocator value_types + +// _HAS_CXX17 and _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS control: +// P0174R2 Deprecating Vestigial Library Parts +// P0521R0 Deprecating shared_ptr::unique() +// P0618R0 Deprecating +// Other C++17 deprecation warnings + +// _HAS_CXX20 directly controls: +// P0020R6 atomic, atomic, atomic +// P0318R1 unwrap_reference, unwrap_ref_decay +// P0325R4 to_array() +// P0356R5 bind_front() +// P0439R0 enum class memory_order +// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view +// P0458R2 contains() For Ordered And Unordered Associative Containers +// P0463R1 endian +// P0482R6 Library Support For char8_t +// (mbrtoc8 and c8rtomb not yet implemented) +// P0487R1 Fixing operator>>(basic_istream&, CharT*) +// P0550R2 remove_cvref +// P0553R4 Rotating And Counting Functions +// P0556R3 ispow2(), ceil2(), floor2(), log2p1() +// (log2p1() is called bit_length() as of D1956) +// P0595R2 is_constant_evaluated() +// P0616R0 Using move() In +// P0631R8 Math Constants +// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type +// P0653R2 to_address() +// P0655R1 visit() +// P0674R1 make_shared() For Arrays +// P0758R1 is_nothrow_convertible +// P0768R1 Library Support For The Spaceship Comparison Operator <=> +// (partially implemented) +// P0769R2 shift_left(), shift_right() +// P0811R3 midpoint(), lerp() +// (partially implemented, lerp() not yet constexpr) +// P0887R1 type_identity +// P0896R4 Ranges +// (partially implemented) +// P0898R3 Standard Library Concepts +// P0919R3 Heterogeneous Lookup For Unordered Containers +// P0966R1 string::reserve() Should Not Shrink +// P1209R0 erase_if(), erase() +// P1227R2 Signed std::ssize(), Unsigned span::size() +// (partially implemented) +// P1357R1 is_bounded_array, is_unbounded_array +// P1612R1 Relocating endian To +// P1651R0 bind_front() Should Not Unwrap reference_wrapper +// P1690R1 Refining Heterogeneous Lookup For Unordered Containers +// P1754R1 Rename Concepts To standard_case +// P????R? directory_entry::clear_cache() + +// _HAS_CXX20 and _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS control: +// P0767R1 Deprecating is_pod +// Other C++20 deprecation warnings + +// Parallel Algorithms Notes +// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. +// This implementation parallelizes several common algorithm calls, but not all. +// +// The following algorithms are parallelized. +// * adjacent_difference +// * adjacent_find +// * all_of +// * any_of +// * count +// * count_if +// * equal +// * exclusive_scan +// * find +// * find_end +// * find_first_of +// * find_if +// * find_if_not +// * for_each +// * for_each_n +// * inclusive_scan +// * is_heap +// * is_heap_until +// * is_partitioned +// * is_sorted +// * is_sorted_until +// * mismatch +// * none_of +// * partition +// * reduce +// * remove +// * remove_if +// * replace +// * replace_if +// * search +// * search_n +// * set_difference +// * set_intersection +// * sort +// * stable_sort +// * transform +// * transform_exclusive_scan +// * transform_inclusive_scan +// * transform_reduce +// +// The following are not presently parallelized: +// +// No apparent parallelism performance improvement on target hardware; all algorithms which +// merely copy or permute elements with no branches are typically memory bandwidth limited. +// * copy +// * copy_n +// * fill +// * fill_n +// * move +// * reverse +// * reverse_copy +// * rotate +// * rotate_copy +// * shift_left +// * shift_right +// * swap_ranges +// +// Confusion over user parallelism requirements exists; likely in the above category anyway. +// * generate +// * generate_n +// +// Effective parallelism suspected to be infeasible. +// * partial_sort +// * partial_sort_copy +// +// Not yet evaluated; parallelism may be implemented in a future release and is suspected to be beneficial. +// * copy_if +// * includes +// * inplace_merge +// * lexicographical_compare +// * max_element +// * merge +// * min_element +// * minmax_element +// * nth_element +// * partition_copy +// * remove_copy +// * remove_copy_if +// * replace_copy +// * replace_copy_if +// * set_symmetric_difference +// * set_union +// * stable_partition +// * unique +// * unique_copy + +#include +#include // The _HAS_CXX tags must be defined before including this. + +#ifndef _STL_WARNING_LEVEL +#if defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 +#define _STL_WARNING_LEVEL 4 +#else // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 +#define _STL_WARNING_LEVEL 3 +#endif // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 +#endif // _STL_WARNING_LEVEL + +#if _STL_WARNING_LEVEL < 3 +#error _STL_WARNING_LEVEL cannot be less than 3. +#endif // _STL_WARNING_LEVEL < 3 + +#if _STL_WARNING_LEVEL > 4 +#error _STL_WARNING_LEVEL cannot be greater than 4. +#endif // _STL_WARNING_LEVEL > 4 + +// _HAS_NODISCARD (in vcruntime.h) controls: +// [[nodiscard]] attributes on STL functions + +// Controls whether the STL uses "if constexpr" internally +#ifndef _HAS_IF_CONSTEXPR +#ifdef __CUDACC__ +#define _HAS_IF_CONSTEXPR 0 +#else // __CUDACC__ +#define _HAS_IF_CONSTEXPR 1 +#endif // __CUDACC__ +#endif // _HAS_IF_CONSTEXPR + +// Controls whether the STL uses "conditional explicit" internally +#ifndef _HAS_CONDITIONAL_EXPLICIT +#ifdef __cpp_conditional_explicit +#define _HAS_CONDITIONAL_EXPLICIT 1 +#elif defined(__CUDACC__) +#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION +#elif defined(__clang__) +#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION, LLVM-42694 +#else // vvv C1XX or non-CUDA EDG vvv +#define _HAS_CONDITIONAL_EXPLICIT 1 +#endif // ^^^ C1XX or non-CUDA EDG ^^^ +#endif // _HAS_CONDITIONAL_EXPLICIT + +// warning C4577: 'noexcept' used with no exception handling mode specified; +// termination on exception is not guaranteed. Specify /EHsc (/Wall) +#if _HAS_EXCEPTIONS +#define _STL_DISABLED_WARNING_C4577 +#else // _HAS_EXCEPTIONS +#define _STL_DISABLED_WARNING_C4577 4577 +#endif // _HAS_EXCEPTIONS + +// warning C4984: 'if constexpr' is a C++17 language extension +#if !_HAS_CXX17 && _HAS_IF_CONSTEXPR +#define _STL_DISABLED_WARNING_C4984 4984 +#else // !_HAS_CXX17 && _HAS_IF_CONSTEXPR +#define _STL_DISABLED_WARNING_C4984 +#endif // !_HAS_CXX17 && _HAS_IF_CONSTEXPR + +// warning C5053: support for 'explicit()' in C++17 and earlier is a vendor extension +#if !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT +#define _STL_DISABLED_WARNING_C5053 5053 +#else // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT +#define _STL_DISABLED_WARNING_C5053 +#endif // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT + +#ifndef _STL_EXTRA_DISABLED_WARNINGS +#define _STL_EXTRA_DISABLED_WARNINGS +#endif // _STL_EXTRA_DISABLED_WARNINGS + +// warning C4180: qualifier applied to function type has no meaning; ignored +// warning C4412: function signature contains type 'meow'; C++ objects are unsafe to pass between pure code +// and mixed or native. (/Wall) +// warning C4455: literal suffix identifiers that do not start with an underscore are reserved +// warning C4472: 'meow' is a native enum: add an access specifier (private/public) +// to declare a managed enum (/Wall) +// warning C4494: Ignoring __declspec(allocator) because the function return type is not a pointer or reference +// warning C4514: unreferenced inline function has been removed (/Wall) +// warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; +// structured exceptions (SEH) are no longer caught (/Wall) +// warning C4574: 'MACRO' is defined to be '0': did you mean to use '#if MACRO'? (/Wall) +// warning C4582: 'union': constructor is not implicitly called (/Wall) +// warning C4583: 'union': destructor is not implicitly called (/Wall) +// warning C4587: behavior change: constructor is no longer implicitly called (/Wall) +// warning C4588: behavior change: destructor is no longer implicitly called (/Wall) +// warning C4619: #pragma warning: there is no warning number 'number' (/Wall) +// warning C4623: default constructor was implicitly defined as deleted (/Wall) +// warning C4625: copy constructor was implicitly defined as deleted (/Wall) +// warning C4626: assignment operator was implicitly defined as deleted (/Wall) +// warning C4643: Forward declaring 'meow' in namespace std is not permitted by the C++ Standard. (/Wall) +// warning C4702: unreachable code +// warning C4793: function compiled as native +// warning C4820: 'N' bytes padding added after data member 'meow' (/Wall) +// warning C4988: variable declared outside class/function scope (/Wall /d1WarnOnGlobals) +// warning C5026: move constructor was implicitly defined as deleted (/Wall) +// warning C5027: move assignment operator was implicitly defined as deleted (/Wall) +// warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified (/Wall) + +#ifndef _STL_DISABLED_WARNINGS +// clang-format off +#define _STL_DISABLED_WARNINGS \ + 4180 4412 4455 4472 4494 4514 4571 4574 4582 4583 \ + 4587 4588 4619 4623 4625 4626 4643 4702 4793 4820 \ + 4988 5026 5027 5045 \ + _STL_DISABLED_WARNING_C4577 \ + _STL_DISABLED_WARNING_C4984 \ + _STL_DISABLED_WARNING_C5053 \ + _STL_EXTRA_DISABLED_WARNINGS +// clang-format on +#endif // _STL_DISABLED_WARNINGS + +// warning: constexpr if is a C++17 extension [-Wc++17-extensions] +// warning: user-defined literal suffixes not starting with '_' are reserved [-Wuser-defined-literals] +// warning: unknown pragma ignored [-Wunknown-pragmas] +#ifndef _STL_DISABLE_CLANG_WARNINGS +#ifdef __clang__ +// clang-format off +#define _STL_DISABLE_CLANG_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wuser-defined-literals\"") \ + _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +// clang-format on +#else // __clang__ +#define _STL_DISABLE_CLANG_WARNINGS +#endif // __clang__ +#endif // _STL_DISABLE_CLANG_WARNINGS + +#ifndef _STL_RESTORE_CLANG_WARNINGS +#ifdef __clang__ +#define _STL_RESTORE_CLANG_WARNINGS _Pragma("clang diagnostic pop") +#else // __clang__ +#define _STL_RESTORE_CLANG_WARNINGS +#endif // __clang__ +#endif // _STL_RESTORE_CLANG_WARNINGS + +// clang-format off +#ifndef _STL_DISABLE_DEPRECATED_WARNING +#ifdef __clang__ +#define _STL_DISABLE_DEPRECATED_WARNING \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#else // __clang__ +#define _STL_DISABLE_DEPRECATED_WARNING \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) // was declared deprecated +#endif // __clang__ +#endif // _STL_DISABLE_DEPRECATED_WARNING +// clang-format on + +#ifndef _STL_RESTORE_DEPRECATED_WARNING +#ifdef __clang__ +#define _STL_RESTORE_DEPRECATED_WARNING _Pragma("clang diagnostic pop") +#else // __clang__ +#define _STL_RESTORE_DEPRECATED_WARNING __pragma(warning(pop)) +#endif // __clang__ +#endif // _STL_RESTORE_DEPRECATED_WARNING + +#define _CPPLIB_VER 650 +#define _MSVC_STL_VERSION 142 +#define _MSVC_STL_UPDATE 201911L + +#ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH +#ifdef __EDG__ +// not attempting to detect __EDG_VERSION__ being less than expected +#elif defined(__clang__) +#if __clang_major__ < 9 +#error STL1000: Unexpected compiler version, expected Clang 9.0.0 or newer. +#endif // ^^^ old Clang ^^^ +#elif defined(_MSC_VER) +#if _MSC_VER < 1924 // Coarse-grained, not inspecting _MSC_FULL_VER +#error STL1001: Unexpected compiler version, expected MSVC 19.24 or newer. +#endif // ^^^ old MSVC ^^^ +#else // vvv other compilers vvv +// not attempting to detect other compilers +#endif // ^^^ other compilers ^^^ +#endif // _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH + +#ifndef _HAS_STATIC_RTTI +#define _HAS_STATIC_RTTI 1 +#endif // _HAS_STATIC_RTTI + +#if defined(_CPPRTTI) && !_HAS_STATIC_RTTI +#error /GR implies _HAS_STATIC_RTTI. +#endif // defined(_CPPRTTI) && !_HAS_STATIC_RTTI + +// C++17 constexpr additions +#if _HAS_CXX17 +#define _CONSTEXPR17 constexpr +#else // ^^^ has C++17 constexpr additions / no C++17 constexpr additions vvv +#define _CONSTEXPR17 inline +#endif // _HAS_CXX17 + +// P0607R0 Inline Variables For The STL +#if _HAS_CXX17 +#define _INLINE_VAR inline +#else // _HAS_CXX17 +#define _INLINE_VAR +#endif // _HAS_CXX17 + +// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff +#ifndef _HAS_AUTO_PTR_ETC +#define _HAS_AUTO_PTR_ETC (!_HAS_CXX17) +#endif // _HAS_AUTO_PTR_ETC + +// P0003R5 Removing Dynamic Exception Specifications +#ifndef _HAS_UNEXPECTED +#define _HAS_UNEXPECTED (!_HAS_CXX17) +#endif // _HAS_UNEXPECTED + +// P0004R1 Removing Deprecated Iostreams Aliases +#ifndef _HAS_OLD_IOSTREAMS_MEMBERS +#define _HAS_OLD_IOSTREAMS_MEMBERS (!_HAS_CXX17) +#endif // _HAS_OLD_IOSTREAMS_MEMBERS + +// P0298R3 std::byte +#ifndef _HAS_STD_BYTE +#define _HAS_STD_BYTE _HAS_CXX17 // inspected by GSL, do not remove +#endif // _HAS_STD_BYTE + +// P0302R1 Removing Allocator Support In std::function +// LWG-2385 function::assign allocator argument doesn't make sense +// LWG-2921 packaged_task and type-erased allocators +// LWG-2976 Dangling uses_allocator specialization for packaged_task +#ifndef _HAS_FUNCTION_ALLOCATOR_SUPPORT +#define _HAS_FUNCTION_ALLOCATOR_SUPPORT (!_HAS_CXX17) +#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT + +// The non-Standard std::tr1 namespace and TR1-only machinery +#ifndef _HAS_TR1_NAMESPACE +#define _HAS_TR1_NAMESPACE (!_HAS_CXX17) +#endif // _HAS_TR1_NAMESPACE + +// STL4000 is "_STATIC_CPPLIB is deprecated", currently in yvals.h +// STL4001 is "/clr:pure is deprecated", currently in yvals.h + +#if _HAS_TR1_NAMESPACE +#ifdef _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING +#define _DEPRECATE_TR1_NAMESPACE +#else // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING +#define _DEPRECATE_TR1_NAMESPACE \ + [[deprecated( \ + "warning STL4002: " \ + "The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED. You can " \ + "define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING to acknowledge that you have received this warning.")]] +#endif // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING +#endif // _HAS_TR1_NAMESPACE + +// STL4003 was "The non-Standard std::identity struct is deprecated and will be REMOVED." + +// Enforcement of matching allocator value_types +#ifndef _ENFORCE_MATCHING_ALLOCATORS +#define _ENFORCE_MATCHING_ALLOCATORS _HAS_CXX17 +#endif // _ENFORCE_MATCHING_ALLOCATORS + +#define _MISMATCHED_ALLOCATOR_MESSAGE(_CONTAINER, _VALUE_TYPE) \ + _CONTAINER " requires that Allocator's value_type match " _VALUE_TYPE \ + " (See N4659 26.2.1 [container.requirements.general]/16 allocator_type)" \ + " Either fix the allocator value_type or define _ENFORCE_MATCHING_ALLOCATORS=0" \ + " to suppress this diagnostic." + +// Enforcement of Standard facet specializations +#ifndef _ENFORCE_FACET_SPECIALIZATIONS +#define _ENFORCE_FACET_SPECIALIZATIONS 0 +#endif // _ENFORCE_FACET_SPECIALIZATIONS + +#define _FACET_SPECIALIZATION_MESSAGE \ + "Unsupported facet specialization; see N4800 27.3.1.1.1 [locale.category]. " \ + "Either use a Standard specialization or define _ENFORCE_FACET_SPECIALIZATIONS=0 " \ + "to suppress this diagnostic." + +// To improve compiler throughput, use 'hidden friend' operators in instead of non-members that are +// depicted in the Standard. +#ifndef _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS +#define _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS 1 +#endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS + +#if _HAS_IF_CONSTEXPR +#define _CONSTEXPR_IF constexpr +#else // _HAS_IF_CONSTEXPR +#define _CONSTEXPR_IF +#endif // _HAS_IF_CONSTEXPR + +#ifdef __clang__ +#define _CONSTEVAL consteval +#else // ^^^ supports consteval / no consteval vvv +#define _CONSTEVAL constexpr +#endif // ^^^ no consteval ^^^ + +// Controls whether the STL will force /fp:fast to enable vectorization of algorithms defined +// in the standard as special cases; such as reduce, transform_reduce, inclusive_scan, exclusive_scan +#ifndef _STD_VECTORIZE_WITH_FLOAT_CONTROL +#ifdef _M_FP_EXCEPT +#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 0 +#else // ^^^ floating point exceptions enabled / floating point exceptions disabled (default) vvv +#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 1 +#endif // _M_FP_EXCEPT +#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL + +// P0174R2 Deprecating Vestigial Library Parts +// P0521R0 Deprecating shared_ptr::unique() +// Other C++17 deprecation warnings + +// N4659 D.4 [depr.cpp.headers] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_C_HEADER \ + [[deprecated("warning STL4004: " \ + ", , , and are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_C_HEADER +#endif // ^^^ warning disabled ^^^ + +// N4659 D.6 [depr.str.strstreams] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_STRSTREAM \ + [[deprecated("warning STL4005: is deprecated in C++17. " \ + "You can define _SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_STRSTREAM +#endif // ^^^ warning disabled ^^^ + +// N4659 D.7 [depr.uncaught] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION \ + [[deprecated("warning STL4006: " \ + "std::uncaught_exception() is deprecated in C++17. " \ + "It is superseded by std::uncaught_exceptions(), plural. " \ + "You can define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION +#endif // ^^^ warning disabled ^^^ + +// N4659 D.8.1 [depr.weak.result_type] +// N4659 D.8.2 [depr.func.adaptor.typedefs] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS \ + [[deprecated( \ + "warning STL4007: Many result_type typedefs " \ + "and all argument_type, first_argument_type, and second_argument_type typedefs are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS +#endif // ^^^ warning disabled ^^^ + +// N4659 D.8.3 [depr.negators] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_NEGATORS \ + [[deprecated("warning STL4008: " \ + "std::not1(), std::not2(), std::unary_negate, and std::binary_negate are deprecated in C++17. " \ + "They are superseded by std::not_fn(). " \ + "You can define _SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_NEGATORS +#endif // ^^^ warning disabled ^^^ + +// STL4009 was "std::allocator is deprecated in C++17" + +// N4659 D.9 [depr.default.allocator] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS \ + [[deprecated("warning STL4010: " \ + "Various members of std::allocator are deprecated in C++17. " \ + "Use std::allocator_traits instead of accessing these members directly. " \ + "You can define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS +#endif // ^^^ warning disabled ^^^ + +// N4659 D.10 [depr.storage.iterator] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR \ + [[deprecated("warning STL4011: " \ + "std::raw_storage_iterator is deprecated in C++17. " \ + "Consider using the std::uninitialized_copy() family of algorithms instead. " \ + "You can define _SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR +#endif // ^^^ warning disabled ^^^ + +// N4659 D.11 [depr.temporary.buffer] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_TEMPORARY_BUFFER \ + [[deprecated("warning STL4012: " \ + "std::get_temporary_buffer() and std::return_temporary_buffer() are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_TEMPORARY_BUFFER +#endif // ^^^ warning disabled ^^^ + +// N4659 D.12 [depr.meta.types] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_IS_LITERAL_TYPE \ + [[deprecated("warning STL4013: " \ + "std::is_literal_type and std::is_literal_type_v are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_IS_LITERAL_TYPE +#endif // ^^^ warning disabled ^^^ + +// N4659 D.12 [depr.meta.types] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_RESULT_OF \ + [[deprecated("warning STL4014: " \ + "std::result_of and std::result_of_t are deprecated in C++17. " \ + "They are superseded by std::invoke_result and std::invoke_result_t. " \ + "You can define _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_RESULT_OF +#endif // ^^^ warning disabled ^^^ + +// N4659 D.13 [depr.iterator.primitives] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS \ + [[deprecated( \ + "warning STL4015: " \ + "The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. " \ + "(The header is NOT deprecated.) The C++ Standard has never required user-defined iterators to " \ + "derive from std::iterator. To fix this warning, stop deriving from std::iterator and start providing " \ + "publicly accessible typedefs named iterator_category, value_type, difference_type, pointer, and reference. " \ + "Note that value_type is required to be non-const, even for constant iterators. " \ + "You can define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS +#endif // ^^^ warning disabled ^^^ + +// N4659 D.14 [depr.util.smartptr.shared.obs] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE \ + [[deprecated("warning STL4016: " \ + "std::shared_ptr::unique() is deprecated in C++17. " \ + "You can define _SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE +#endif // ^^^ warning disabled ^^^ + +// N4659 D.15 [depr.locale.stdcvt] +// N4659 D.16 [depr.conversions] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_CODECVT_HEADER \ + [[deprecated( \ + "warning STL4017: " \ + "std::wbuffer_convert, std::wstring_convert, and the header (containing std::codecvt_mode, " \ + "std::codecvt_utf8, std::codecvt_utf16, and std::codecvt_utf8_utf16) are deprecated in C++17. " \ + "(The std::codecvt class template is NOT deprecated.) " \ + "The C++ Standard doesn't provide equivalent non-deprecated functionality; " \ + "consider using MultiByteToWideChar() and WideCharToMultiByte() from instead. " \ + "You can define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_CODECVT_HEADER +#endif // ^^^ warning disabled ^^^ + +// STL4018 was "The non-Standard std::tr2::sys namespace is deprecated and will be REMOVED." + +#ifdef _SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING +#define _DEPRECATE_FPOS_SEEKPOS +#else // ^^^ warning disabled / warning enabled vvv +#define _DEPRECATE_FPOS_SEEKPOS \ + [[deprecated("warning STL4019: " \ + "The member std::fpos::seekpos() is non-Standard, and is preserved only for compatibility with " \ + "workarounds for old versions of Visual C++. It will be removed in a future release, and in this " \ + "release always returns 0. Please use standards-conforming mechanisms to manipulate fpos, such as " \ + "conversions to and from streamoff, or an integral type, instead. If you are receiving this message " \ + "while compiling Boost.IOStreams, a fix has been submitted upstream to make Boost use " \ + "standards-conforming mechanisms, as it does for other compilers. You can define " \ + "_SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING to acknowledge that you have received this warning, " \ + "or define _REMOVE_FPOS_SEEKPOS to remove std::fpos::seekpos entirely.")]] +#endif // ^^^ warning enabled ^^^ + +// P0482R6 Library Support For char8_t +// Other C++20 deprecation warnings + +// N4810 D.16 [depr.locale.category] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_CODECVT_FACETS \ + [[deprecated("warning STL4020: " \ + "std::codecvt, std::codecvt, " \ + "std::codecvt_byname, and std::codecvt_byname " \ + "are deprecated in C++20 and replaced by specializations with a second argument of type char8_t. " \ + "You can define _SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_CODECVT_FACETS +#endif // ^^^ warning disabled ^^^ + +// N4810 D.17 [depr.fs.path.factory] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_U8PATH_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_U8PATH \ + [[deprecated("warning STL4021: " \ + "The std::filesystem::u8path() overloads are deprecated in C++20. " \ + "The constructors of std::filesystem::path provide equivalent functionality via construction from " \ + "u8string, u8string_view, or iterators with value_type char8_t." \ + "You can define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_U8PATH +#endif // ^^^ warning disabled ^^^ + +#if !defined(_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING) +#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND \ + [[deprecated( \ + "warning STL4022: " \ + "The hash_meow and unordered_meow containers' non-Standard lower_bound() member was provided for interface " \ + "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ + "hash_meow or unordered_meow containers. Please use the find() member instead. You can define " \ + "_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND +#endif // ^^^ warning disabled ^^^ + +#if !defined(_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING) +#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND \ + [[deprecated( \ + "warning STL4023: " \ + "The hash_meow and unordered_meow containers' non-Standard upper_bound() member was provided for interface " \ + "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ + "hash_meow or unordered_meow containers. Please use the second iterator returned by the " \ + "equal_range() member instead. You can define " \ + "_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND +#endif // ^^^ warning disabled ^^^ + +// P0966R1 [depr.string.capacity] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT \ + [[deprecated("warning STL4024: " \ + "std::string::reserve() without an argument is deprecated in C++20. " \ + "To shrink the string's capacity, use std::string::shrink_to_fit() instead. Otherwise, provide an " \ + "argument to std::string::reserve(). " \ + "You can define _SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT +#endif // ^^^ warning disabled ^^^ + +// P0767R1 [depr.meta.types] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_IS_POD_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_IS_POD \ + [[deprecated("warning STL4025: " \ + "std::is_pod and std::is_pod_v are deprecated in C++20. " \ + "The std::is_trivially_copyable and/or std::is_standard_layout traits likely suit your use case. " \ + "You can define _SILENCE_CXX20_IS_POD_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_IS_POD +#endif // ^^^ warning disabled ^^^ + +#if _HAS_CXX20 && !defined(_SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING) +#define _DEPRECATE_EXPERIMENTAL_ERASE \ + [[deprecated("warning STL4026: " \ + "std::experimental::erase() and std::experimental::erase_if() are deprecated by Microsoft and will " \ + "be REMOVED. They are superseded by std::erase() and std::erase_if(). " \ + "You can define _SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING to acknowledge that you have " \ + "received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_EXPERIMENTAL_ERASE +#endif // ^^^ warning disabled ^^^ + +// next warning number: STL4027 + + +// LIBRARY FEATURE-TEST MACROS + +// C++14 +#define __cpp_lib_chrono_udls 201304L +#define __cpp_lib_complex_udls 201309L +#define __cpp_lib_exchange_function 201304L +#define __cpp_lib_generic_associative_lookup 201304L +#define __cpp_lib_integer_sequence 201304L +#define __cpp_lib_integral_constant_callable 201304L +#define __cpp_lib_is_final 201402L +#define __cpp_lib_is_null_pointer 201309L +#define __cpp_lib_make_reverse_iterator 201402L +#define __cpp_lib_make_unique 201304L +#define __cpp_lib_null_iterators 201304L +#define __cpp_lib_quoted_string_io 201304L +#define __cpp_lib_result_of_sfinae 201210L +#define __cpp_lib_robust_nonmodifying_seq_ops 201304L +#ifndef _M_CEE +#define __cpp_lib_shared_timed_mutex 201402L +#endif // _M_CEE +#define __cpp_lib_string_udls 201304L +#define __cpp_lib_transformation_trait_aliases 201304L +#define __cpp_lib_tuple_element_t 201402L +#define __cpp_lib_tuples_by_type 201304L + +// C++17 +#define __cpp_lib_addressof_constexpr 201603L +#define __cpp_lib_allocator_traits_is_always_equal 201411L +#define __cpp_lib_as_const 201510L +#define __cpp_lib_bool_constant 201505L +#define __cpp_lib_enable_shared_from_this 201603L +#define __cpp_lib_incomplete_container_elements 201505L +#define __cpp_lib_invoke 201411L +#define __cpp_lib_logical_traits 201510L +#define __cpp_lib_map_try_emplace 201411L +#define __cpp_lib_nonmember_container_access 201411L +#ifndef _USING_V110_SDK71_ +#define __cpp_lib_shared_mutex 201505L +#endif // _USING_V110_SDK71_ +#define __cpp_lib_shared_ptr_arrays 201707L +#define __cpp_lib_transparent_operators 201510L +#define __cpp_lib_type_trait_variable_templates 201510L +#define __cpp_lib_uncaught_exceptions 201411L +#define __cpp_lib_unordered_map_try_emplace 201411L +#define __cpp_lib_void_t 201411L + +#if _HAS_CXX17 +#define __cpp_lib_any 201606L +#define __cpp_lib_apply 201603L +#define __cpp_lib_array_constexpr 201803L +#define __cpp_lib_atomic_is_always_lock_free 201603L +#define __cpp_lib_boyer_moore_searcher 201603L +#if _HAS_STD_BYTE +#define __cpp_lib_byte 201603L +#endif // _HAS_STD_BYTE +#define __cpp_lib_chrono 201611L +#define __cpp_lib_clamp 201603L +#ifndef _M_CEE +#define __cpp_lib_execution 201603L +#endif // _M_CEE +#define __cpp_lib_filesystem 201703L +#define __cpp_lib_gcd_lcm 201606L +#define __cpp_lib_hardware_interference_size 201703L +#define __cpp_lib_has_unique_object_representations 201606L +#define __cpp_lib_hypot 201603L +#define __cpp_lib_is_aggregate 201703L +#define __cpp_lib_is_invocable 201703L +#define __cpp_lib_is_swappable 201603L +#define __cpp_lib_launder 201606L +#define __cpp_lib_make_from_tuple 201606L +#define __cpp_lib_math_special_functions 201603L +#define __cpp_lib_memory_resource 201603L +#define __cpp_lib_node_extract 201606L +#define __cpp_lib_not_fn 201603L +#define __cpp_lib_optional 201606L +#ifndef _M_CEE +#define __cpp_lib_parallel_algorithm 201603L +#endif // _M_CEE +#define __cpp_lib_raw_memory_algorithms 201606L +#define __cpp_lib_sample 201603L +#define __cpp_lib_scoped_lock 201703L +#define __cpp_lib_shared_ptr_weak_type 201606L +#define __cpp_lib_string_view 201803L +#define __cpp_lib_to_chars 201611L +#define __cpp_lib_variant 201606L +#else // _HAS_CXX17 +#define __cpp_lib_chrono 201510L +#endif // _HAS_CXX17 + +// C++20 +#if _HAS_CXX20 +#define __cpp_lib_atomic_float 201711L +#define __cpp_lib_bind_front 201907L + +#if defined(__clang__) || defined(__EDG__) +#define __cpp_lib_bitops 201907L +#else // ^^^ Clang and EDG / MSVC vvv +// a future MSVC update will embed CPU feature detection into intrinsics +// TRANSITION, VSO-1020212 +#endif // defined(__clang__) || defined(__EDG__) + +#define __cpp_lib_bounded_array_traits 201902L + +#ifdef __cpp_char8_t +#define __cpp_lib_char8_t 201811L +#endif // __cpp_char8_t + +#if defined(__cpp_concepts) && __cpp_concepts > 201507L +#define __cpp_lib_concepts 201907L + +// P0898R3 (as modified by P1754R1) std::boolean +#ifndef _HAS_STD_BOOLEAN +#define _HAS_STD_BOOLEAN 1 +#endif // _HAS_STD_BOOLEAN +#endif // defined(__cpp_concepts) && __cpp_concepts > 201507L + +#define __cpp_lib_endian 201907L +#define __cpp_lib_erase_if 201811L +#define __cpp_lib_generic_unordered_lookup 201811L +#define __cpp_lib_int_pow2 201806L + +#if defined(__clang__) || defined(__EDG__) \ + || (defined(_MSC_VER) && _MSC_VER >= 1925 && !(_MSC_FULL_VER == 192528318 && _MSC_BUILD == 97)) +#define __cpp_lib_is_constant_evaluated 201811L +#endif // TRANSITION, VS 2019 16.5 Preview 2 and toolset update + +#define __cpp_lib_list_remove_return_type 201806L +#define __cpp_lib_math_constants 201907L +#define __cpp_lib_nothrow_convertible 201806L +#define __cpp_lib_remove_cvref 201711L +#define __cpp_lib_shift 201806L +#define __cpp_lib_ssize 201902L +#define __cpp_lib_starts_ends_with 201711L +#define __cpp_lib_to_address 201711L +#define __cpp_lib_to_array 201907L +#define __cpp_lib_type_identity 201806L +#define __cpp_lib_unwrap_ref 201811L +#endif // _HAS_CXX20 + +// EXPERIMENTAL +#define __cpp_lib_experimental_erase_if 201411L +#define __cpp_lib_experimental_filesystem 201406L + + +#ifdef _RTC_CONVERSION_CHECKS_ENABLED +#ifndef _ALLOW_RTCc_IN_STL +#error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ +compiler option, or define _ALLOW_RTCc_IN_STL to acknowledge that you have received this warning. +#endif // _ALLOW_RTCc_IN_STL +#endif // _RTC_CONVERSION_CHECKS_ENABLED + +#ifndef _DECLSPEC_ALLOCATOR +#ifdef __clang__ +#define _DECLSPEC_ALLOCATOR +#else // ^^^ Clang / non-Clang vvv +#define _DECLSPEC_ALLOCATOR __declspec(allocator) +#endif // ^^^ non-Clang ^^^ +#endif // _DECLSPEC_ALLOCATOR + +#define _STRINGIZEX(x) #x +#define _STRINGIZE(x) _STRINGIZEX(x) +#define _EMPTY_ARGUMENT // for empty macro argument + +// NAMESPACE +#define _STD_BEGIN namespace std { +#define _STD_END } +#define _STD ::std:: +#define _RANGES ::std::ranges:: + +// We use the stdext (standard extension) namespace to contain extensions that are not part of the current standard +#define _STDEXT_BEGIN namespace stdext { +#define _STDEXT_END } +#define _STDEXT ::stdext:: + +#ifdef __cplusplus +#define _CSTD :: + +#define _EXTERN_C extern "C" { +#define _END_EXTERN_C } +#else // ^^^ __cplusplus / !__cplusplus vvv +#define _CSTD + +#define _EXTERN_C +#define _END_EXTERN_C +#endif // __cplusplus + +#ifdef _M_CEE_PURE +#define _EXTERN_C_UNLESS_PURE +#define _END_EXTERN_C_UNLESS_PURE +#define _STATIC_UNLESS_PURE // Avoid warning C4640: construction of local static object is not thread-safe (/Wall) +#else // ^^^ _M_CEE_PURE / !_M_CEE_PURE vvv +#define _EXTERN_C_UNLESS_PURE _EXTERN_C +#define _END_EXTERN_C_UNLESS_PURE _END_EXTERN_C +#define _STATIC_UNLESS_PURE static +#endif // _M_CEE_PURE + +#if defined(MRTDLL) && !defined(_CRTBLD) +#error In yvals_core.h, defined(MRTDLL) implies defined(_CRTBLD); !defined(_CRTBLD) implies !defined(MRTDLL) +#endif // defined(MRTDLL) && !defined(_CRTBLD) + +#if defined(MRTDLL) && !defined(_M_CEE_PURE) +#error In yvals_core.h, defined(MRTDLL) implies defined(_M_CEE_PURE); !defined(_M_CEE_PURE) implies !defined(MRTDLL) +#endif // defined(MRTDLL) && !defined(_M_CEE_PURE) + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _YVALS_CORE_H_ From e1fd4a1ad90953203d3366bcbca8c31b27c8c15b Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 5 Dec 2019 20:34:42 +0100 Subject: [PATCH 15/52] Replace #if defined with #ifdef --- stl/inc/memory | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 6245544c0da..30b02e9a465 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1254,13 +1254,13 @@ private: // clang-format off template -#if defined(__cpp_concepts) +#ifdef __cpp_concepts requires(!is_array_v<_Ty0>) -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); // clang-format on -#if defined(__cpp_concepts) +#ifdef __cpp_concepts // clang-format off template requires is_unbounded_array_v<_Ty0> @@ -1278,17 +1278,17 @@ private: requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); // clang-format on -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts // clang-format off template -#if defined(__cpp_concepts) +#ifdef __cpp_concepts requires(!is_array_v<_Ty0>) -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); // clang-format on -#if defined(__cpp_concepts) +#ifdef __cpp_concepts // clang-format off template requires is_unbounded_array_v<_Ty0> @@ -1307,7 +1307,7 @@ private: requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); // clang-format on -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts template void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px @@ -1556,7 +1556,7 @@ private: } }; -#if defined(__cpp_concepts) +#ifdef __cpp_concepts template constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { return (_Val1 % _Val2 == 0) ? (_Val1 / _Val2) : (_Val1 / _Val2 + 1); @@ -1753,7 +1753,7 @@ private: delete this; } }; -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts // CLASS TEMPLATE _Ebco_base template class _Uninitialized_rev_destroying_backout_al { // struct to undo partially constructed ranges in // _Uninitialized_xxx_al algorithms @@ -2043,14 +2043,14 @@ private: _Deallocate_plain(_Al, this); } }; -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts // FUNCTION TEMPLATE make_shared // clang-format off template -#if defined(__cpp_concepts) +#ifdef __cpp_concepts requires(!is_array_v<_Ty>) -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; @@ -2059,7 +2059,7 @@ _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr } // clang-format on -#if defined(__cpp_concepts) +#ifdef __cpp_concepts // clang-format off template requires is_unbounded_array_v<_Ty> @@ -2122,14 +2122,14 @@ _NODISCARD shared_ptr<_Ty> make_shared( return _Ret; } // clang-format on -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts // FUNCTION TEMPLATE allocate_shared // clang-format off template -#if defined(__cpp_concepts) +#ifdef __cpp_concepts requires(!is_array_v<_Ty>) -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts _NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether @@ -2147,7 +2147,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( } // clang-format on -#if defined(__cpp_concepts) +#ifdef __cpp_concepts // clang-format off template requires is_unbounded_array_v<_Ty> @@ -2225,7 +2225,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( return _Ret; } // clang-format on -#endif // defined(__cpp_concepts) +#endif // __cpp_concepts // CLASS TEMPLATE weak_ptr template From f9292874fa2e151c1614e80a0da328a086dd45b8 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 5 Dec 2019 20:43:47 +0100 Subject: [PATCH 16/52] Formatting --- stl/inc/memory | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 30b02e9a465..e2b5359bec0 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1255,7 +1255,7 @@ private: // clang-format off template #ifdef __cpp_concepts - requires(!is_array_v<_Ty0>) + requires (!is_array_v<_Ty0>) #endif // __cpp_concepts friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); // clang-format on @@ -1283,7 +1283,7 @@ private: // clang-format off template #ifdef __cpp_concepts - requires(!is_array_v<_Ty0>) + requires (!is_array_v<_Ty0>) #endif // __cpp_concepts friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); // clang-format on @@ -2049,7 +2049,7 @@ private: // clang-format off template #ifdef __cpp_concepts - requires(!is_array_v<_Ty>) + requires (!is_array_v<_Ty>) #endif // __cpp_concepts _NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); @@ -2128,7 +2128,7 @@ _NODISCARD shared_ptr<_Ty> make_shared( // clang-format off template #ifdef __cpp_concepts - requires(!is_array_v<_Ty>) + requires (!is_array_v<_Ty>) #endif // __cpp_concepts _NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object From 04d67e655b6e953d2f6fffda2f8e7af8f31d47e4 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Fri, 6 Dec 2019 14:18:06 +0100 Subject: [PATCH 17/52] Increase feature-test macro only if concepts are supported --- stl/inc/yvals_core.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 70b1272b954..3087139cc6f 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -896,7 +896,13 @@ #ifndef _USING_V110_SDK71_ #define __cpp_lib_shared_mutex 201505L #endif // _USING_V110_SDK71_ -#define __cpp_lib_shared_ptr_arrays 201707L + +#ifdef __cpp_concepts +#define __cpp_lib_shared_ptr_arrays 201707L +#else // __cpp_concepts +#define __cpp_lib_shared_ptr_arrays 201611L +#endif // __cpp_concepts + #define __cpp_lib_transparent_operators 201510L #define __cpp_lib_type_trait_variable_templates 201510L #define __cpp_lib_uncaught_exceptions 201411L From 8c98cf204a61e8e8bd32c5c88eae1e4b778bd9bc Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Thu, 12 Dec 2019 16:30:57 +0100 Subject: [PATCH 18/52] Update yvals_core.h --- stl/inc/yvals_core.h | 2136 +++++++++++++++++++++--------------------- 1 file changed, 1068 insertions(+), 1068 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 37c27b5706d..934377f8d1a 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1,1068 +1,1068 @@ -// yvals_core.h internal header (core) - -// Copyright (c) Microsoft Corporation. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#pragma once -#ifndef _YVALS_CORE_H_ -#define _YVALS_CORE_H_ -#ifndef _STL_COMPILER_PREPROCESSOR -// All STL headers avoid exposing their contents when included by various -// non-C++-compiler tools to avoid breaking builds when we use newer language -// features in the headers than such tools understand. -#if defined(RC_INVOKED) || defined(Q_MOC_RUN) || defined(__midl) -#define _STL_COMPILER_PREPROCESSOR 0 -#else -#define _STL_COMPILER_PREPROCESSOR 1 -#endif -#endif // _STL_COMPILER_PREPROCESSOR - -#if _STL_COMPILER_PREPROCESSOR -// Implemented unconditionally: -// N3911 void_t -// N4089 Safe Conversions In unique_ptr -// N4169 invoke() -// N4258 noexcept Cleanups -// N4259 uncaught_exceptions() -// N4277 Trivially Copyable reference_wrapper -// N4279 insert_or_assign()/try_emplace() For map/unordered_map -// N4280 size(), empty(), data() -// N4366 Precisely Constraining unique_ptr Assignment -// N4387 Improving pair And tuple -// N4389 bool_constant -// N4508 shared_mutex (Untimed) -// N4510 Supporting Incomplete Types In vector/list/forward_list -// P0006R0 Variable Templates For Type Traits (is_same_v, etc.) -// P0007R1 as_const() -// P0013R1 Logical Operator Type Traits (conjunction, etc.) -// P0033R1 Rewording enable_shared_from_this -// P0063R3 C11 Standard Library -// P0074R0 owner_less<> -// P0092R1 floor(), ceil(), round(), abs() -// P0340R3 SFINAE-Friendly underlying_type -// P0414R2 shared_ptr, shared_ptr -// P0418R2 atomic compare_exchange memory_order Requirements -// P0435R1 Overhauling common_type -// P0497R0 Fixing shared_ptr For Arrays -// P0513R0 Poisoning hash -// P0516R0 Marking shared_future Copying As noexcept -// P0517R0 Constructing future_error From future_errc -// P0548R1 Tweaking common_type And duration -// P0558R1 Resolving atomic Named Base Class Inconsistencies -// P0599R1 noexcept hash -// P0738R2 istream_iterator Cleanup -// P0771R1 noexcept For std::function's Move Constructor -// P0777R1 Avoiding Unnecessary decay -// P0809R0 Comparing Unordered Containers -// P0941R2 Feature-Test Macros -// P0972R0 noexcept For zero(), min(), max() -// P1164R1 Making create_directory() Intuitive -// P1902R1 Missing Feature-Test Macros 2017-2019 - -// _HAS_CXX17 directly controls: -// P0005R4 not_fn() -// P0024R2 Parallel Algorithms -// P0025R1 clamp() -// P0030R1 hypot(x, y, z) -// P0031R0 constexpr For (Again) And -// P0032R3 Homogeneous Interface For variant/any/optional -// P0040R3 Extending Memory Management Tools -// P0067R5 Elementary String Conversions -// P0083R3 Splicing Maps And Sets -// P0084R2 Emplace Return Type -// P0088R3 -// P0137R1 launder() -// P0152R1 atomic::is_always_lock_free -// P0154R1 hardware_destructive_interference_size, etc. -// P0156R2 scoped_lock -// P0163R0 shared_ptr::weak_type -// P0185R1 is_swappable, is_nothrow_swappable -// P0209R2 make_from_tuple() -// P0218R1 -// P0220R1 , , , , apply(), sample(), Boyer-Moore search() -// P0226R1 Mathematical Special Functions -// P0253R1 Fixing Searcher Return Types -// P0254R2 Integrating string_view And std::string -// P0258R2 has_unique_object_representations -// P0272R1 Non-const basic_string::data() -// P0295R0 gcd(), lcm() -// P0307R2 Making Optional Greater Equal Again -// P0336R1 Renaming Parallel Execution Policies -// P0337R0 Deleting polymorphic_allocator Assignment -// P0358R1 Fixes For not_fn() -// P0393R3 Making Variant Greater Equal -// P0394R4 Parallel Algorithms Should terminate() For Exceptions -// P0403R1 UDLs For ("meow"sv, etc.) -// P0426R1 constexpr For char_traits -// P0433R2 Deduction Guides For The STL -// P0452R1 Unifying Parallel Algorithms -// P0504R0 Revisiting in_place_t/in_place_type_t/in_place_index_t -// P0505R0 constexpr For (Again) -// P0508R0 Clarifying insert_return_type -// P0510R0 Rejecting variants Of Nothing, Arrays, References, And Incomplete Types -// P0602R4 Propagating Copy/Move Triviality In variant/optional -// P0604R0 invoke_result, is_invocable, is_nothrow_invocable -// P0607R0 Inline Variables For The STL -// P0682R1 Repairing Elementary String Conversions -// P0739R0 Improving Class Template Argument Deduction For The STL -// P0858R0 Constexpr Iterator Requirements - -// _HAS_CXX17 indirectly controls: -// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff -// P0003R5 Removing Dynamic Exception Specifications -// P0004R1 Removing Deprecated Iostreams Aliases -// P0298R3 std::byte -// P0302R1 Removing Allocator Support In std::function -// LWG-2385 function::assign allocator argument doesn't make sense -// LWG-2921 packaged_task and type-erased allocators -// LWG-2976 Dangling uses_allocator specialization for packaged_task -// The non-Standard std::tr1 namespace and TR1-only machinery -// Enforcement of matching allocator value_types - -// _HAS_CXX17 and _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS control: -// P0174R2 Deprecating Vestigial Library Parts -// P0521R0 Deprecating shared_ptr::unique() -// P0618R0 Deprecating -// Other C++17 deprecation warnings - -// _HAS_CXX20 directly controls: -// P0020R6 atomic, atomic, atomic -// P0318R1 unwrap_reference, unwrap_ref_decay -// P0325R4 to_array() -// P0356R5 bind_front() -// P0439R0 enum class memory_order -// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view -// P0458R2 contains() For Ordered And Unordered Associative Containers -// P0463R1 endian -// P0482R6 Library Support For char8_t -// (mbrtoc8 and c8rtomb not yet implemented) -// P0487R1 Fixing operator>>(basic_istream&, CharT*) -// P0550R2 remove_cvref -// P0553R4 Rotating And Counting Functions -// P0556R3 ispow2(), ceil2(), floor2(), log2p1() -// (log2p1() is called bit_length() as of D1956) -// P0595R2 is_constant_evaluated() -// P0616R0 Using move() In -// P0631R8 Math Constants -// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type -// P0653R2 to_address() -// P0655R1 visit() -// P0674R1 make_shared() For Arrays -// P0758R1 is_nothrow_convertible -// P0768R1 Library Support For The Spaceship Comparison Operator <=> -// (partially implemented) -// P0769R2 shift_left(), shift_right() -// P0811R3 midpoint(), lerp() -// (partially implemented, lerp() not yet constexpr) -// P0887R1 type_identity -// P0896R4 Ranges -// (partially implemented) -// P0898R3 Standard Library Concepts -// P0919R3 Heterogeneous Lookup For Unordered Containers -// P0966R1 string::reserve() Should Not Shrink -// P1209R0 erase_if(), erase() -// P1227R2 Signed std::ssize(), Unsigned span::size() -// (partially implemented) -// P1357R1 is_bounded_array, is_unbounded_array -// P1612R1 Relocating endian To -// P1651R0 bind_front() Should Not Unwrap reference_wrapper -// P1690R1 Refining Heterogeneous Lookup For Unordered Containers -// P1754R1 Rename Concepts To standard_case -// P????R? directory_entry::clear_cache() - -// _HAS_CXX20 and _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS control: -// P0767R1 Deprecating is_pod -// Other C++20 deprecation warnings - -// Parallel Algorithms Notes -// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. -// This implementation parallelizes several common algorithm calls, but not all. -// -// The following algorithms are parallelized. -// * adjacent_difference -// * adjacent_find -// * all_of -// * any_of -// * count -// * count_if -// * equal -// * exclusive_scan -// * find -// * find_end -// * find_first_of -// * find_if -// * find_if_not -// * for_each -// * for_each_n -// * inclusive_scan -// * is_heap -// * is_heap_until -// * is_partitioned -// * is_sorted -// * is_sorted_until -// * mismatch -// * none_of -// * partition -// * reduce -// * remove -// * remove_if -// * replace -// * replace_if -// * search -// * search_n -// * set_difference -// * set_intersection -// * sort -// * stable_sort -// * transform -// * transform_exclusive_scan -// * transform_inclusive_scan -// * transform_reduce -// -// The following are not presently parallelized: -// -// No apparent parallelism performance improvement on target hardware; all algorithms which -// merely copy or permute elements with no branches are typically memory bandwidth limited. -// * copy -// * copy_n -// * fill -// * fill_n -// * move -// * reverse -// * reverse_copy -// * rotate -// * rotate_copy -// * shift_left -// * shift_right -// * swap_ranges -// -// Confusion over user parallelism requirements exists; likely in the above category anyway. -// * generate -// * generate_n -// -// Effective parallelism suspected to be infeasible. -// * partial_sort -// * partial_sort_copy -// -// Not yet evaluated; parallelism may be implemented in a future release and is suspected to be beneficial. -// * copy_if -// * includes -// * inplace_merge -// * lexicographical_compare -// * max_element -// * merge -// * min_element -// * minmax_element -// * nth_element -// * partition_copy -// * remove_copy -// * remove_copy_if -// * replace_copy -// * replace_copy_if -// * set_symmetric_difference -// * set_union -// * stable_partition -// * unique -// * unique_copy - -#include -#include // The _HAS_CXX tags must be defined before including this. - -#ifndef _STL_WARNING_LEVEL -#if defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#define _STL_WARNING_LEVEL 4 -#else // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#define _STL_WARNING_LEVEL 3 -#endif // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 -#endif // _STL_WARNING_LEVEL - -#if _STL_WARNING_LEVEL < 3 -#error _STL_WARNING_LEVEL cannot be less than 3. -#endif // _STL_WARNING_LEVEL < 3 - -#if _STL_WARNING_LEVEL > 4 -#error _STL_WARNING_LEVEL cannot be greater than 4. -#endif // _STL_WARNING_LEVEL > 4 - -// _HAS_NODISCARD (in vcruntime.h) controls: -// [[nodiscard]] attributes on STL functions - -// Controls whether the STL uses "if constexpr" internally -#ifndef _HAS_IF_CONSTEXPR -#ifdef __CUDACC__ -#define _HAS_IF_CONSTEXPR 0 -#else // __CUDACC__ -#define _HAS_IF_CONSTEXPR 1 -#endif // __CUDACC__ -#endif // _HAS_IF_CONSTEXPR - -// Controls whether the STL uses "conditional explicit" internally -#ifndef _HAS_CONDITIONAL_EXPLICIT -#ifdef __cpp_conditional_explicit -#define _HAS_CONDITIONAL_EXPLICIT 1 -#elif defined(__CUDACC__) -#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION -#elif defined(__clang__) -#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION, LLVM-42694 -#else // vvv C1XX or non-CUDA EDG vvv -#define _HAS_CONDITIONAL_EXPLICIT 1 -#endif // ^^^ C1XX or non-CUDA EDG ^^^ -#endif // _HAS_CONDITIONAL_EXPLICIT - -// warning C4577: 'noexcept' used with no exception handling mode specified; -// termination on exception is not guaranteed. Specify /EHsc (/Wall) -#if _HAS_EXCEPTIONS -#define _STL_DISABLED_WARNING_C4577 -#else // _HAS_EXCEPTIONS -#define _STL_DISABLED_WARNING_C4577 4577 -#endif // _HAS_EXCEPTIONS - -// warning C4984: 'if constexpr' is a C++17 language extension -#if !_HAS_CXX17 && _HAS_IF_CONSTEXPR -#define _STL_DISABLED_WARNING_C4984 4984 -#else // !_HAS_CXX17 && _HAS_IF_CONSTEXPR -#define _STL_DISABLED_WARNING_C4984 -#endif // !_HAS_CXX17 && _HAS_IF_CONSTEXPR - -// warning C5053: support for 'explicit()' in C++17 and earlier is a vendor extension -#if !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT -#define _STL_DISABLED_WARNING_C5053 5053 -#else // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT -#define _STL_DISABLED_WARNING_C5053 -#endif // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT - -#ifndef _STL_EXTRA_DISABLED_WARNINGS -#define _STL_EXTRA_DISABLED_WARNINGS -#endif // _STL_EXTRA_DISABLED_WARNINGS - -// warning C4180: qualifier applied to function type has no meaning; ignored -// warning C4412: function signature contains type 'meow'; C++ objects are unsafe to pass between pure code -// and mixed or native. (/Wall) -// warning C4455: literal suffix identifiers that do not start with an underscore are reserved -// warning C4472: 'meow' is a native enum: add an access specifier (private/public) -// to declare a managed enum (/Wall) -// warning C4494: Ignoring __declspec(allocator) because the function return type is not a pointer or reference -// warning C4514: unreferenced inline function has been removed (/Wall) -// warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; -// structured exceptions (SEH) are no longer caught (/Wall) -// warning C4574: 'MACRO' is defined to be '0': did you mean to use '#if MACRO'? (/Wall) -// warning C4582: 'union': constructor is not implicitly called (/Wall) -// warning C4583: 'union': destructor is not implicitly called (/Wall) -// warning C4587: behavior change: constructor is no longer implicitly called (/Wall) -// warning C4588: behavior change: destructor is no longer implicitly called (/Wall) -// warning C4619: #pragma warning: there is no warning number 'number' (/Wall) -// warning C4623: default constructor was implicitly defined as deleted (/Wall) -// warning C4625: copy constructor was implicitly defined as deleted (/Wall) -// warning C4626: assignment operator was implicitly defined as deleted (/Wall) -// warning C4643: Forward declaring 'meow' in namespace std is not permitted by the C++ Standard. (/Wall) -// warning C4702: unreachable code -// warning C4793: function compiled as native -// warning C4820: 'N' bytes padding added after data member 'meow' (/Wall) -// warning C4988: variable declared outside class/function scope (/Wall /d1WarnOnGlobals) -// warning C5026: move constructor was implicitly defined as deleted (/Wall) -// warning C5027: move assignment operator was implicitly defined as deleted (/Wall) -// warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified (/Wall) - -#ifndef _STL_DISABLED_WARNINGS -// clang-format off -#define _STL_DISABLED_WARNINGS \ - 4180 4412 4455 4472 4494 4514 4571 4574 4582 4583 \ - 4587 4588 4619 4623 4625 4626 4643 4702 4793 4820 \ - 4988 5026 5027 5045 \ - _STL_DISABLED_WARNING_C4577 \ - _STL_DISABLED_WARNING_C4984 \ - _STL_DISABLED_WARNING_C5053 \ - _STL_EXTRA_DISABLED_WARNINGS -// clang-format on -#endif // _STL_DISABLED_WARNINGS - -// warning: constexpr if is a C++17 extension [-Wc++17-extensions] -// warning: user-defined literal suffixes not starting with '_' are reserved [-Wuser-defined-literals] -// warning: unknown pragma ignored [-Wunknown-pragmas] -#ifndef _STL_DISABLE_CLANG_WARNINGS -#ifdef __clang__ -// clang-format off -#define _STL_DISABLE_CLANG_WARNINGS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ - _Pragma("clang diagnostic ignored \"-Wuser-defined-literals\"") \ - _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") -// clang-format on -#else // __clang__ -#define _STL_DISABLE_CLANG_WARNINGS -#endif // __clang__ -#endif // _STL_DISABLE_CLANG_WARNINGS - -#ifndef _STL_RESTORE_CLANG_WARNINGS -#ifdef __clang__ -#define _STL_RESTORE_CLANG_WARNINGS _Pragma("clang diagnostic pop") -#else // __clang__ -#define _STL_RESTORE_CLANG_WARNINGS -#endif // __clang__ -#endif // _STL_RESTORE_CLANG_WARNINGS - -// clang-format off -#ifndef _STL_DISABLE_DEPRECATED_WARNING -#ifdef __clang__ -#define _STL_DISABLE_DEPRECATED_WARNING \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") -#else // __clang__ -#define _STL_DISABLE_DEPRECATED_WARNING \ - __pragma(warning(push)) \ - __pragma(warning(disable : 4996)) // was declared deprecated -#endif // __clang__ -#endif // _STL_DISABLE_DEPRECATED_WARNING -// clang-format on - -#ifndef _STL_RESTORE_DEPRECATED_WARNING -#ifdef __clang__ -#define _STL_RESTORE_DEPRECATED_WARNING _Pragma("clang diagnostic pop") -#else // __clang__ -#define _STL_RESTORE_DEPRECATED_WARNING __pragma(warning(pop)) -#endif // __clang__ -#endif // _STL_RESTORE_DEPRECATED_WARNING - -#define _CPPLIB_VER 650 -#define _MSVC_STL_VERSION 142 -#define _MSVC_STL_UPDATE 201912L - -#ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH -#ifdef __EDG__ -// not attempting to detect __EDG_VERSION__ being less than expected -#elif defined(__clang__) -#if __clang_major__ < 9 -#error STL1000: Unexpected compiler version, expected Clang 9.0.0 or newer. -#endif // ^^^ old Clang ^^^ -#elif defined(_MSC_VER) -#if _MSC_VER < 1924 // Coarse-grained, not inspecting _MSC_FULL_VER -#error STL1001: Unexpected compiler version, expected MSVC 19.24 or newer. -#endif // ^^^ old MSVC ^^^ -#else // vvv other compilers vvv -// not attempting to detect other compilers -#endif // ^^^ other compilers ^^^ -#endif // _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH - -#ifndef _HAS_STATIC_RTTI -#define _HAS_STATIC_RTTI 1 -#endif // _HAS_STATIC_RTTI - -#if defined(_CPPRTTI) && !_HAS_STATIC_RTTI -#error /GR implies _HAS_STATIC_RTTI. -#endif // defined(_CPPRTTI) && !_HAS_STATIC_RTTI - -// C++17 constexpr additions -#if _HAS_CXX17 -#define _CONSTEXPR17 constexpr -#else // ^^^ has C++17 constexpr additions / no C++17 constexpr additions vvv -#define _CONSTEXPR17 inline -#endif // _HAS_CXX17 - -// P0607R0 Inline Variables For The STL -#if _HAS_CXX17 -#define _INLINE_VAR inline -#else // _HAS_CXX17 -#define _INLINE_VAR -#endif // _HAS_CXX17 - -// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff -#ifndef _HAS_AUTO_PTR_ETC -#define _HAS_AUTO_PTR_ETC (!_HAS_CXX17) -#endif // _HAS_AUTO_PTR_ETC - -// P0003R5 Removing Dynamic Exception Specifications -#ifndef _HAS_UNEXPECTED -#define _HAS_UNEXPECTED (!_HAS_CXX17) -#endif // _HAS_UNEXPECTED - -// P0004R1 Removing Deprecated Iostreams Aliases -#ifndef _HAS_OLD_IOSTREAMS_MEMBERS -#define _HAS_OLD_IOSTREAMS_MEMBERS (!_HAS_CXX17) -#endif // _HAS_OLD_IOSTREAMS_MEMBERS - -// P0298R3 std::byte -#ifndef _HAS_STD_BYTE -#define _HAS_STD_BYTE _HAS_CXX17 // inspected by GSL, do not remove -#endif // _HAS_STD_BYTE - -// P0302R1 Removing Allocator Support In std::function -// LWG-2385 function::assign allocator argument doesn't make sense -// LWG-2921 packaged_task and type-erased allocators -// LWG-2976 Dangling uses_allocator specialization for packaged_task -#ifndef _HAS_FUNCTION_ALLOCATOR_SUPPORT -#define _HAS_FUNCTION_ALLOCATOR_SUPPORT (!_HAS_CXX17) -#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT - -// The non-Standard std::tr1 namespace and TR1-only machinery -#ifndef _HAS_TR1_NAMESPACE -#define _HAS_TR1_NAMESPACE (!_HAS_CXX17) -#endif // _HAS_TR1_NAMESPACE - -// STL4000 is "_STATIC_CPPLIB is deprecated", currently in yvals.h -// STL4001 is "/clr:pure is deprecated", currently in yvals.h - -#if _HAS_TR1_NAMESPACE -#ifdef _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -#define _DEPRECATE_TR1_NAMESPACE -#else // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -#define _DEPRECATE_TR1_NAMESPACE \ - [[deprecated( \ - "warning STL4002: " \ - "The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED. You can " \ - "define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING to acknowledge that you have received this warning.")]] -#endif // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING -#endif // _HAS_TR1_NAMESPACE - -// STL4003 was "The non-Standard std::identity struct is deprecated and will be REMOVED." - -// Enforcement of matching allocator value_types -#ifndef _ENFORCE_MATCHING_ALLOCATORS -#define _ENFORCE_MATCHING_ALLOCATORS _HAS_CXX17 -#endif // _ENFORCE_MATCHING_ALLOCATORS - -#define _MISMATCHED_ALLOCATOR_MESSAGE(_CONTAINER, _VALUE_TYPE) \ - _CONTAINER " requires that Allocator's value_type match " _VALUE_TYPE \ - " (See N4659 26.2.1 [container.requirements.general]/16 allocator_type)" \ - " Either fix the allocator value_type or define _ENFORCE_MATCHING_ALLOCATORS=0" \ - " to suppress this diagnostic." - -// Enforcement of Standard facet specializations -#ifndef _ENFORCE_FACET_SPECIALIZATIONS -#define _ENFORCE_FACET_SPECIALIZATIONS 0 -#endif // _ENFORCE_FACET_SPECIALIZATIONS - -#define _FACET_SPECIALIZATION_MESSAGE \ - "Unsupported facet specialization; see N4800 27.3.1.1.1 [locale.category]. " \ - "Either use a Standard specialization or define _ENFORCE_FACET_SPECIALIZATIONS=0 " \ - "to suppress this diagnostic." - -// To improve compiler throughput, use 'hidden friend' operators in instead of non-members that are -// depicted in the Standard. -#ifndef _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS -#define _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS 1 -#endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS - -#if _HAS_IF_CONSTEXPR -#define _CONSTEXPR_IF constexpr -#else // _HAS_IF_CONSTEXPR -#define _CONSTEXPR_IF -#endif // _HAS_IF_CONSTEXPR - -#ifdef __clang__ -#define _CONSTEVAL consteval -#else // ^^^ supports consteval / no consteval vvv -#define _CONSTEVAL constexpr -#endif // ^^^ no consteval ^^^ - -// Controls whether the STL will force /fp:fast to enable vectorization of algorithms defined -// in the standard as special cases; such as reduce, transform_reduce, inclusive_scan, exclusive_scan -#ifndef _STD_VECTORIZE_WITH_FLOAT_CONTROL -#ifdef _M_FP_EXCEPT -#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 0 -#else // ^^^ floating point exceptions enabled / floating point exceptions disabled (default) vvv -#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 1 -#endif // _M_FP_EXCEPT -#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL - -// P0174R2 Deprecating Vestigial Library Parts -// P0521R0 Deprecating shared_ptr::unique() -// Other C++17 deprecation warnings - -// N4659 D.4 [depr.cpp.headers] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_C_HEADER \ - [[deprecated("warning STL4004: " \ - ", , , and are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_C_HEADER -#endif // ^^^ warning disabled ^^^ - -// N4659 D.6 [depr.str.strstreams] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_STRSTREAM \ - [[deprecated("warning STL4005: is deprecated in C++17. " \ - "You can define _SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_STRSTREAM -#endif // ^^^ warning disabled ^^^ - -// N4659 D.7 [depr.uncaught] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION \ - [[deprecated("warning STL4006: " \ - "std::uncaught_exception() is deprecated in C++17. " \ - "It is superseded by std::uncaught_exceptions(), plural. " \ - "You can define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION -#endif // ^^^ warning disabled ^^^ - -// N4659 D.8.1 [depr.weak.result_type] -// N4659 D.8.2 [depr.func.adaptor.typedefs] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS \ - [[deprecated( \ - "warning STL4007: Many result_type typedefs " \ - "and all argument_type, first_argument_type, and second_argument_type typedefs are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS -#endif // ^^^ warning disabled ^^^ - -// N4659 D.8.3 [depr.negators] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_NEGATORS \ - [[deprecated("warning STL4008: " \ - "std::not1(), std::not2(), std::unary_negate, and std::binary_negate are deprecated in C++17. " \ - "They are superseded by std::not_fn(). " \ - "You can define _SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_NEGATORS -#endif // ^^^ warning disabled ^^^ - -// STL4009 was "std::allocator is deprecated in C++17" - -// N4659 D.9 [depr.default.allocator] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS \ - [[deprecated("warning STL4010: " \ - "Various members of std::allocator are deprecated in C++17. " \ - "Use std::allocator_traits instead of accessing these members directly. " \ - "You can define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS -#endif // ^^^ warning disabled ^^^ - -// N4659 D.10 [depr.storage.iterator] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR \ - [[deprecated("warning STL4011: " \ - "std::raw_storage_iterator is deprecated in C++17. " \ - "Consider using the std::uninitialized_copy() family of algorithms instead. " \ - "You can define _SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR -#endif // ^^^ warning disabled ^^^ - -// N4659 D.11 [depr.temporary.buffer] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_TEMPORARY_BUFFER \ - [[deprecated("warning STL4012: " \ - "std::get_temporary_buffer() and std::return_temporary_buffer() are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_TEMPORARY_BUFFER -#endif // ^^^ warning disabled ^^^ - -// N4659 D.12 [depr.meta.types] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_IS_LITERAL_TYPE \ - [[deprecated("warning STL4013: " \ - "std::is_literal_type and std::is_literal_type_v are deprecated in C++17. " \ - "You can define _SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_IS_LITERAL_TYPE -#endif // ^^^ warning disabled ^^^ - -// N4659 D.12 [depr.meta.types] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_RESULT_OF \ - [[deprecated("warning STL4014: " \ - "std::result_of and std::result_of_t are deprecated in C++17. " \ - "They are superseded by std::invoke_result and std::invoke_result_t. " \ - "You can define _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_RESULT_OF -#endif // ^^^ warning disabled ^^^ - -// N4659 D.13 [depr.iterator.primitives] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS \ - [[deprecated( \ - "warning STL4015: " \ - "The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. " \ - "(The header is NOT deprecated.) The C++ Standard has never required user-defined iterators to " \ - "derive from std::iterator. To fix this warning, stop deriving from std::iterator and start providing " \ - "publicly accessible typedefs named iterator_category, value_type, difference_type, pointer, and reference. " \ - "Note that value_type is required to be non-const, even for constant iterators. " \ - "You can define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS -#endif // ^^^ warning disabled ^^^ - -// N4659 D.14 [depr.util.smartptr.shared.obs] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE \ - [[deprecated("warning STL4016: " \ - "std::shared_ptr::unique() is deprecated in C++17. " \ - "You can define _SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE -#endif // ^^^ warning disabled ^^^ - -// N4659 D.15 [depr.locale.stdcvt] -// N4659 D.16 [depr.conversions] -#if _HAS_CXX17 && !defined(_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) -#define _CXX17_DEPRECATE_CODECVT_HEADER \ - [[deprecated( \ - "warning STL4017: " \ - "std::wbuffer_convert, std::wstring_convert, and the header (containing std::codecvt_mode, " \ - "std::codecvt_utf8, std::codecvt_utf16, and std::codecvt_utf8_utf16) are deprecated in C++17. " \ - "(The std::codecvt class template is NOT deprecated.) " \ - "The C++ Standard doesn't provide equivalent non-deprecated functionality; " \ - "consider using MultiByteToWideChar() and WideCharToMultiByte() from instead. " \ - "You can define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX17_DEPRECATE_CODECVT_HEADER -#endif // ^^^ warning disabled ^^^ - -// STL4018 was "The non-Standard std::tr2::sys namespace is deprecated and will be REMOVED." - -#ifdef _SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING -#define _DEPRECATE_FPOS_SEEKPOS -#else // ^^^ warning disabled / warning enabled vvv -#define _DEPRECATE_FPOS_SEEKPOS \ - [[deprecated("warning STL4019: " \ - "The member std::fpos::seekpos() is non-Standard, and is preserved only for compatibility with " \ - "workarounds for old versions of Visual C++. It will be removed in a future release, and in this " \ - "release always returns 0. Please use standards-conforming mechanisms to manipulate fpos, such as " \ - "conversions to and from streamoff, or an integral type, instead. If you are receiving this message " \ - "while compiling Boost.IOStreams, a fix has been submitted upstream to make Boost use " \ - "standards-conforming mechanisms, as it does for other compilers. You can define " \ - "_SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING to acknowledge that you have received this warning, " \ - "or define _REMOVE_FPOS_SEEKPOS to remove std::fpos::seekpos entirely.")]] -#endif // ^^^ warning enabled ^^^ - -// P0482R6 Library Support For char8_t -// Other C++20 deprecation warnings - -// N4810 D.16 [depr.locale.category] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_CODECVT_FACETS \ - [[deprecated("warning STL4020: " \ - "std::codecvt, std::codecvt, " \ - "std::codecvt_byname, and std::codecvt_byname " \ - "are deprecated in C++20 and replaced by specializations with a second argument of type char8_t. " \ - "You can define _SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_CODECVT_FACETS -#endif // ^^^ warning disabled ^^^ - -// N4810 D.17 [depr.fs.path.factory] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_U8PATH_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_U8PATH \ - [[deprecated("warning STL4021: " \ - "The std::filesystem::u8path() overloads are deprecated in C++20. " \ - "The constructors of std::filesystem::path provide equivalent functionality via construction from " \ - "u8string, u8string_view, or iterators with value_type char8_t." \ - "You can define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_U8PATH -#endif // ^^^ warning disabled ^^^ - -#if !defined(_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING) -#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND \ - [[deprecated( \ - "warning STL4022: " \ - "The hash_meow and unordered_meow containers' non-Standard lower_bound() member was provided for interface " \ - "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ - "hash_meow or unordered_meow containers. Please use the find() member instead. You can define " \ - "_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND -#endif // ^^^ warning disabled ^^^ - -#if !defined(_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING) -#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND \ - [[deprecated( \ - "warning STL4023: " \ - "The hash_meow and unordered_meow containers' non-Standard upper_bound() member was provided for interface " \ - "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ - "hash_meow or unordered_meow containers. Please use the second iterator returned by the " \ - "equal_range() member instead. You can define " \ - "_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND -#endif // ^^^ warning disabled ^^^ - -// P0966R1 [depr.string.capacity] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT \ - [[deprecated("warning STL4024: " \ - "std::string::reserve() without an argument is deprecated in C++20. " \ - "To shrink the string's capacity, use std::string::shrink_to_fit() instead. Otherwise, provide an " \ - "argument to std::string::reserve(). " \ - "You can define _SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT -#endif // ^^^ warning disabled ^^^ - -// P0767R1 [depr.meta.types] -#if _HAS_CXX20 && !defined(_SILENCE_CXX20_IS_POD_DEPRECATION_WARNING) \ - && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) -#define _CXX20_DEPRECATE_IS_POD \ - [[deprecated("warning STL4025: " \ - "std::is_pod and std::is_pod_v are deprecated in C++20. " \ - "The std::is_trivially_copyable and/or std::is_standard_layout traits likely suit your use case. " \ - "You can define _SILENCE_CXX20_IS_POD_DEPRECATION_WARNING " \ - "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _CXX20_DEPRECATE_IS_POD -#endif // ^^^ warning disabled ^^^ - -#if _HAS_CXX20 && !defined(_SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING) -#define _DEPRECATE_EXPERIMENTAL_ERASE \ - [[deprecated("warning STL4026: " \ - "std::experimental::erase() and std::experimental::erase_if() are deprecated by Microsoft and will " \ - "be REMOVED. They are superseded by std::erase() and std::erase_if(). " \ - "You can define _SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING to acknowledge that you have " \ - "received this warning.")]] -#else // ^^^ warning enabled / warning disabled vvv -#define _DEPRECATE_EXPERIMENTAL_ERASE -#endif // ^^^ warning disabled ^^^ - -// next warning number: STL4027 - - -// LIBRARY FEATURE-TEST MACROS - -// C++14 -#define __cpp_lib_chrono_udls 201304L -#define __cpp_lib_complex_udls 201309L -#define __cpp_lib_exchange_function 201304L -#define __cpp_lib_generic_associative_lookup 201304L -#define __cpp_lib_integer_sequence 201304L -#define __cpp_lib_integral_constant_callable 201304L -#define __cpp_lib_is_final 201402L -#define __cpp_lib_is_null_pointer 201309L -#define __cpp_lib_make_reverse_iterator 201402L -#define __cpp_lib_make_unique 201304L -#define __cpp_lib_null_iterators 201304L -#define __cpp_lib_quoted_string_io 201304L -#define __cpp_lib_result_of_sfinae 201210L -#define __cpp_lib_robust_nonmodifying_seq_ops 201304L -#ifndef _M_CEE -#define __cpp_lib_shared_timed_mutex 201402L -#endif // _M_CEE -#define __cpp_lib_string_udls 201304L -#define __cpp_lib_transformation_trait_aliases 201304L -#define __cpp_lib_tuple_element_t 201402L -#define __cpp_lib_tuples_by_type 201304L - -// C++17 -#define __cpp_lib_addressof_constexpr 201603L -#define __cpp_lib_allocator_traits_is_always_equal 201411L -#define __cpp_lib_as_const 201510L -#define __cpp_lib_bool_constant 201505L -#define __cpp_lib_enable_shared_from_this 201603L -#define __cpp_lib_incomplete_container_elements 201505L -#define __cpp_lib_invoke 201411L -#define __cpp_lib_logical_traits 201510L -#define __cpp_lib_map_try_emplace 201411L -#define __cpp_lib_nonmember_container_access 201411L -#define __cpp_lib_shared_mutex 201505L - -#ifdef __cpp_concepts -#define __cpp_lib_shared_ptr_arrays 201707L -#else // __cpp_concepts -#define __cpp_lib_shared_ptr_arrays 201611L -#endif // __cpp_concepts - -#define __cpp_lib_transparent_operators 201510L -#define __cpp_lib_type_trait_variable_templates 201510L -#define __cpp_lib_uncaught_exceptions 201411L -#define __cpp_lib_unordered_map_try_emplace 201411L -#define __cpp_lib_void_t 201411L - -#if _HAS_CXX17 -#define __cpp_lib_any 201606L -#define __cpp_lib_apply 201603L -#define __cpp_lib_array_constexpr 201803L -#define __cpp_lib_atomic_is_always_lock_free 201603L -#define __cpp_lib_boyer_moore_searcher 201603L -#if _HAS_STD_BYTE -#define __cpp_lib_byte 201603L -#endif // _HAS_STD_BYTE -#define __cpp_lib_chrono 201611L -#define __cpp_lib_clamp 201603L -#ifndef _M_CEE -#define __cpp_lib_execution 201603L -#endif // _M_CEE -#define __cpp_lib_filesystem 201703L -#define __cpp_lib_gcd_lcm 201606L -#define __cpp_lib_hardware_interference_size 201703L -#define __cpp_lib_has_unique_object_representations 201606L -#define __cpp_lib_hypot 201603L -#define __cpp_lib_is_aggregate 201703L -#define __cpp_lib_is_invocable 201703L -#define __cpp_lib_is_swappable 201603L -#define __cpp_lib_launder 201606L -#define __cpp_lib_make_from_tuple 201606L -#define __cpp_lib_math_special_functions 201603L -#define __cpp_lib_memory_resource 201603L -#define __cpp_lib_node_extract 201606L -#define __cpp_lib_not_fn 201603L -#define __cpp_lib_optional 201606L -#ifndef _M_CEE -#define __cpp_lib_parallel_algorithm 201603L -#endif // _M_CEE -#define __cpp_lib_raw_memory_algorithms 201606L -#define __cpp_lib_sample 201603L -#define __cpp_lib_scoped_lock 201703L -#define __cpp_lib_shared_ptr_weak_type 201606L -#define __cpp_lib_string_view 201803L -#define __cpp_lib_to_chars 201611L -#define __cpp_lib_variant 201606L -#else // _HAS_CXX17 -#define __cpp_lib_chrono 201510L -#endif // _HAS_CXX17 - -// C++20 -#if _HAS_CXX20 -#define __cpp_lib_atomic_float 201711L -#define __cpp_lib_bind_front 201907L - -#if defined(__clang__) || defined(__EDG__) -#define __cpp_lib_bitops 201907L -#else // ^^^ Clang and EDG / MSVC vvv -// a future MSVC update will embed CPU feature detection into intrinsics -// TRANSITION, VSO-1020212 -#endif // defined(__clang__) || defined(__EDG__) - -#define __cpp_lib_bounded_array_traits 201902L - -#ifdef __cpp_char8_t -#define __cpp_lib_char8_t 201811L -#endif // __cpp_char8_t - -#if defined(__cpp_concepts) && __cpp_concepts > 201507L -#define __cpp_lib_concepts 201907L - -// P0898R3 (as modified by P1754R1) std::boolean -#ifndef _HAS_STD_BOOLEAN -#define _HAS_STD_BOOLEAN 1 -#endif // _HAS_STD_BOOLEAN -#endif // defined(__cpp_concepts) && __cpp_concepts > 201507L - -#define __cpp_lib_endian 201907L -#define __cpp_lib_erase_if 201811L -#define __cpp_lib_generic_unordered_lookup 201811L -#define __cpp_lib_int_pow2 201806L - -#if defined(__clang__) || defined(__EDG__) || (defined(_MSC_VER) && _MSC_VER >= 1925) -#define __cpp_lib_is_constant_evaluated 201811L -#endif // TRANSITION, VS 2019 16.5 Preview 2 - -#define __cpp_lib_list_remove_return_type 201806L -#define __cpp_lib_math_constants 201907L -#define __cpp_lib_nothrow_convertible 201806L -#define __cpp_lib_remove_cvref 201711L -#define __cpp_lib_shift 201806L -#define __cpp_lib_ssize 201902L -#define __cpp_lib_starts_ends_with 201711L -#define __cpp_lib_to_address 201711L -#define __cpp_lib_to_array 201907L -#define __cpp_lib_type_identity 201806L -#define __cpp_lib_unwrap_ref 201811L -#endif // _HAS_CXX20 - -// EXPERIMENTAL -#define __cpp_lib_experimental_erase_if 201411L -#define __cpp_lib_experimental_filesystem 201406L - - -#ifdef _RTC_CONVERSION_CHECKS_ENABLED -#ifndef _ALLOW_RTCc_IN_STL -#error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ -compiler option, or define _ALLOW_RTCc_IN_STL to acknowledge that you have received this warning. -#endif // _ALLOW_RTCc_IN_STL -#endif // _RTC_CONVERSION_CHECKS_ENABLED - -#ifndef _DECLSPEC_ALLOCATOR -#ifdef __clang__ -#define _DECLSPEC_ALLOCATOR -#else // ^^^ Clang / non-Clang vvv -#define _DECLSPEC_ALLOCATOR __declspec(allocator) -#endif // ^^^ non-Clang ^^^ -#endif // _DECLSPEC_ALLOCATOR - -#define _STRINGIZEX(x) #x -#define _STRINGIZE(x) _STRINGIZEX(x) -#define _EMPTY_ARGUMENT // for empty macro argument - -// NAMESPACE -#define _STD_BEGIN namespace std { -#define _STD_END } -#define _STD ::std:: -#define _RANGES ::std::ranges:: - -// We use the stdext (standard extension) namespace to contain extensions that are not part of the current standard -#define _STDEXT_BEGIN namespace stdext { -#define _STDEXT_END } -#define _STDEXT ::stdext:: - -#ifdef __cplusplus -#define _CSTD :: - -#define _EXTERN_C extern "C" { -#define _END_EXTERN_C } -#else // ^^^ __cplusplus / !__cplusplus vvv -#define _CSTD - -#define _EXTERN_C -#define _END_EXTERN_C -#endif // __cplusplus - -#ifdef _M_CEE_PURE -#define _EXTERN_C_UNLESS_PURE -#define _END_EXTERN_C_UNLESS_PURE -#define _STATIC_UNLESS_PURE // Avoid warning C4640: construction of local static object is not thread-safe (/Wall) -#else // ^^^ _M_CEE_PURE / !_M_CEE_PURE vvv -#define _EXTERN_C_UNLESS_PURE _EXTERN_C -#define _END_EXTERN_C_UNLESS_PURE _END_EXTERN_C -#define _STATIC_UNLESS_PURE static -#endif // _M_CEE_PURE - -#if defined(MRTDLL) && !defined(_CRTBLD) -#error In yvals_core.h, defined(MRTDLL) implies defined(_CRTBLD); !defined(_CRTBLD) implies !defined(MRTDLL) -#endif // defined(MRTDLL) && !defined(_CRTBLD) - -#if defined(MRTDLL) && !defined(_M_CEE_PURE) -#error In yvals_core.h, defined(MRTDLL) implies defined(_M_CEE_PURE); !defined(_M_CEE_PURE) implies !defined(MRTDLL) -#endif // defined(MRTDLL) && !defined(_M_CEE_PURE) - -#endif // _STL_COMPILER_PREPROCESSOR -#endif // _YVALS_CORE_H_ +// yvals_core.h internal header (core) + +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#pragma once +#ifndef _YVALS_CORE_H_ +#define _YVALS_CORE_H_ +#ifndef _STL_COMPILER_PREPROCESSOR +// All STL headers avoid exposing their contents when included by various +// non-C++-compiler tools to avoid breaking builds when we use newer language +// features in the headers than such tools understand. +#if defined(RC_INVOKED) || defined(Q_MOC_RUN) || defined(__midl) +#define _STL_COMPILER_PREPROCESSOR 0 +#else +#define _STL_COMPILER_PREPROCESSOR 1 +#endif +#endif // _STL_COMPILER_PREPROCESSOR + +#if _STL_COMPILER_PREPROCESSOR +// Implemented unconditionally: +// N3911 void_t +// N4089 Safe Conversions In unique_ptr +// N4169 invoke() +// N4258 noexcept Cleanups +// N4259 uncaught_exceptions() +// N4277 Trivially Copyable reference_wrapper +// N4279 insert_or_assign()/try_emplace() For map/unordered_map +// N4280 size(), empty(), data() +// N4366 Precisely Constraining unique_ptr Assignment +// N4387 Improving pair And tuple +// N4389 bool_constant +// N4508 shared_mutex (Untimed) +// N4510 Supporting Incomplete Types In vector/list/forward_list +// P0006R0 Variable Templates For Type Traits (is_same_v, etc.) +// P0007R1 as_const() +// P0013R1 Logical Operator Type Traits (conjunction, etc.) +// P0033R1 Rewording enable_shared_from_this +// P0063R3 C11 Standard Library +// P0074R0 owner_less<> +// P0092R1 floor(), ceil(), round(), abs() +// P0340R3 SFINAE-Friendly underlying_type +// P0414R2 shared_ptr, shared_ptr +// P0418R2 atomic compare_exchange memory_order Requirements +// P0435R1 Overhauling common_type +// P0497R0 Fixing shared_ptr For Arrays +// P0513R0 Poisoning hash +// P0516R0 Marking shared_future Copying As noexcept +// P0517R0 Constructing future_error From future_errc +// P0548R1 Tweaking common_type And duration +// P0558R1 Resolving atomic Named Base Class Inconsistencies +// P0599R1 noexcept hash +// P0738R2 istream_iterator Cleanup +// P0771R1 noexcept For std::function's Move Constructor +// P0777R1 Avoiding Unnecessary decay +// P0809R0 Comparing Unordered Containers +// P0941R2 Feature-Test Macros +// P0972R0 noexcept For zero(), min(), max() +// P1164R1 Making create_directory() Intuitive +// P1902R1 Missing Feature-Test Macros 2017-2019 + +// _HAS_CXX17 directly controls: +// P0005R4 not_fn() +// P0024R2 Parallel Algorithms +// P0025R1 clamp() +// P0030R1 hypot(x, y, z) +// P0031R0 constexpr For (Again) And +// P0032R3 Homogeneous Interface For variant/any/optional +// P0040R3 Extending Memory Management Tools +// P0067R5 Elementary String Conversions +// P0083R3 Splicing Maps And Sets +// P0084R2 Emplace Return Type +// P0088R3 +// P0137R1 launder() +// P0152R1 atomic::is_always_lock_free +// P0154R1 hardware_destructive_interference_size, etc. +// P0156R2 scoped_lock +// P0163R0 shared_ptr::weak_type +// P0185R1 is_swappable, is_nothrow_swappable +// P0209R2 make_from_tuple() +// P0218R1 +// P0220R1 , , , , apply(), sample(), Boyer-Moore search() +// P0226R1 Mathematical Special Functions +// P0253R1 Fixing Searcher Return Types +// P0254R2 Integrating string_view And std::string +// P0258R2 has_unique_object_representations +// P0272R1 Non-const basic_string::data() +// P0295R0 gcd(), lcm() +// P0307R2 Making Optional Greater Equal Again +// P0336R1 Renaming Parallel Execution Policies +// P0337R0 Deleting polymorphic_allocator Assignment +// P0358R1 Fixes For not_fn() +// P0393R3 Making Variant Greater Equal +// P0394R4 Parallel Algorithms Should terminate() For Exceptions +// P0403R1 UDLs For ("meow"sv, etc.) +// P0426R1 constexpr For char_traits +// P0433R2 Deduction Guides For The STL +// P0452R1 Unifying Parallel Algorithms +// P0504R0 Revisiting in_place_t/in_place_type_t/in_place_index_t +// P0505R0 constexpr For (Again) +// P0508R0 Clarifying insert_return_type +// P0510R0 Rejecting variants Of Nothing, Arrays, References, And Incomplete Types +// P0602R4 Propagating Copy/Move Triviality In variant/optional +// P0604R0 invoke_result, is_invocable, is_nothrow_invocable +// P0607R0 Inline Variables For The STL +// P0682R1 Repairing Elementary String Conversions +// P0739R0 Improving Class Template Argument Deduction For The STL +// P0858R0 Constexpr Iterator Requirements + +// _HAS_CXX17 indirectly controls: +// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff +// P0003R5 Removing Dynamic Exception Specifications +// P0004R1 Removing Deprecated Iostreams Aliases +// P0298R3 std::byte +// P0302R1 Removing Allocator Support In std::function +// LWG-2385 function::assign allocator argument doesn't make sense +// LWG-2921 packaged_task and type-erased allocators +// LWG-2976 Dangling uses_allocator specialization for packaged_task +// The non-Standard std::tr1 namespace and TR1-only machinery +// Enforcement of matching allocator value_types + +// _HAS_CXX17 and _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS control: +// P0174R2 Deprecating Vestigial Library Parts +// P0521R0 Deprecating shared_ptr::unique() +// P0618R0 Deprecating +// Other C++17 deprecation warnings + +// _HAS_CXX20 directly controls: +// P0020R6 atomic, atomic, atomic +// P0318R1 unwrap_reference, unwrap_ref_decay +// P0325R4 to_array() +// P0356R5 bind_front() +// P0439R0 enum class memory_order +// P0457R2 starts_with()/ends_with() For basic_string/basic_string_view +// P0458R2 contains() For Ordered And Unordered Associative Containers +// P0463R1 endian +// P0482R6 Library Support For char8_t +// (mbrtoc8 and c8rtomb not yet implemented) +// P0487R1 Fixing operator>>(basic_istream&, CharT*) +// P0550R2 remove_cvref +// P0553R4 Rotating And Counting Functions +// P0556R3 ispow2(), ceil2(), floor2(), log2p1() +// (log2p1() is called bit_length() as of D1956) +// P0595R2 is_constant_evaluated() +// P0616R0 Using move() In +// P0631R8 Math Constants +// P0646R1 list/forward_list remove()/remove_if()/unique() Return size_type +// P0653R2 to_address() +// P0655R1 visit() +// P0674R1 make_shared() For Arrays +// P0758R1 is_nothrow_convertible +// P0768R1 Library Support For The Spaceship Comparison Operator <=> +// (partially implemented) +// P0769R2 shift_left(), shift_right() +// P0811R3 midpoint(), lerp() +// (partially implemented, lerp() not yet constexpr) +// P0887R1 type_identity +// P0896R4 Ranges +// (partially implemented) +// P0898R3 Standard Library Concepts +// P0919R3 Heterogeneous Lookup For Unordered Containers +// P0966R1 string::reserve() Should Not Shrink +// P1209R0 erase_if(), erase() +// P1227R2 Signed std::ssize(), Unsigned span::size() +// (partially implemented) +// P1357R1 is_bounded_array, is_unbounded_array +// P1612R1 Relocating endian To +// P1651R0 bind_front() Should Not Unwrap reference_wrapper +// P1690R1 Refining Heterogeneous Lookup For Unordered Containers +// P1754R1 Rename Concepts To standard_case +// P????R? directory_entry::clear_cache() + +// _HAS_CXX20 and _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS control: +// P0767R1 Deprecating is_pod +// Other C++20 deprecation warnings + +// Parallel Algorithms Notes +// C++ allows an implementation to implement parallel algorithms as calls to the serial algorithms. +// This implementation parallelizes several common algorithm calls, but not all. +// +// The following algorithms are parallelized. +// * adjacent_difference +// * adjacent_find +// * all_of +// * any_of +// * count +// * count_if +// * equal +// * exclusive_scan +// * find +// * find_end +// * find_first_of +// * find_if +// * find_if_not +// * for_each +// * for_each_n +// * inclusive_scan +// * is_heap +// * is_heap_until +// * is_partitioned +// * is_sorted +// * is_sorted_until +// * mismatch +// * none_of +// * partition +// * reduce +// * remove +// * remove_if +// * replace +// * replace_if +// * search +// * search_n +// * set_difference +// * set_intersection +// * sort +// * stable_sort +// * transform +// * transform_exclusive_scan +// * transform_inclusive_scan +// * transform_reduce +// +// The following are not presently parallelized: +// +// No apparent parallelism performance improvement on target hardware; all algorithms which +// merely copy or permute elements with no branches are typically memory bandwidth limited. +// * copy +// * copy_n +// * fill +// * fill_n +// * move +// * reverse +// * reverse_copy +// * rotate +// * rotate_copy +// * shift_left +// * shift_right +// * swap_ranges +// +// Confusion over user parallelism requirements exists; likely in the above category anyway. +// * generate +// * generate_n +// +// Effective parallelism suspected to be infeasible. +// * partial_sort +// * partial_sort_copy +// +// Not yet evaluated; parallelism may be implemented in a future release and is suspected to be beneficial. +// * copy_if +// * includes +// * inplace_merge +// * lexicographical_compare +// * max_element +// * merge +// * min_element +// * minmax_element +// * nth_element +// * partition_copy +// * remove_copy +// * remove_copy_if +// * replace_copy +// * replace_copy_if +// * set_symmetric_difference +// * set_union +// * stable_partition +// * unique +// * unique_copy + +#include +#include // The _HAS_CXX tags must be defined before including this. + +#ifndef _STL_WARNING_LEVEL +#if defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 +#define _STL_WARNING_LEVEL 4 +#else // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 +#define _STL_WARNING_LEVEL 3 +#endif // defined(_MSVC_WARNING_LEVEL) && _MSVC_WARNING_LEVEL >= 4 +#endif // _STL_WARNING_LEVEL + +#if _STL_WARNING_LEVEL < 3 +#error _STL_WARNING_LEVEL cannot be less than 3. +#endif // _STL_WARNING_LEVEL < 3 + +#if _STL_WARNING_LEVEL > 4 +#error _STL_WARNING_LEVEL cannot be greater than 4. +#endif // _STL_WARNING_LEVEL > 4 + +// _HAS_NODISCARD (in vcruntime.h) controls: +// [[nodiscard]] attributes on STL functions + +// Controls whether the STL uses "if constexpr" internally +#ifndef _HAS_IF_CONSTEXPR +#ifdef __CUDACC__ +#define _HAS_IF_CONSTEXPR 0 +#else // __CUDACC__ +#define _HAS_IF_CONSTEXPR 1 +#endif // __CUDACC__ +#endif // _HAS_IF_CONSTEXPR + +// Controls whether the STL uses "conditional explicit" internally +#ifndef _HAS_CONDITIONAL_EXPLICIT +#ifdef __cpp_conditional_explicit +#define _HAS_CONDITIONAL_EXPLICIT 1 +#elif defined(__CUDACC__) +#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION +#elif defined(__clang__) +#define _HAS_CONDITIONAL_EXPLICIT 0 // TRANSITION, LLVM-42694 +#else // vvv C1XX or non-CUDA EDG vvv +#define _HAS_CONDITIONAL_EXPLICIT 1 +#endif // ^^^ C1XX or non-CUDA EDG ^^^ +#endif // _HAS_CONDITIONAL_EXPLICIT + +// warning C4577: 'noexcept' used with no exception handling mode specified; +// termination on exception is not guaranteed. Specify /EHsc (/Wall) +#if _HAS_EXCEPTIONS +#define _STL_DISABLED_WARNING_C4577 +#else // _HAS_EXCEPTIONS +#define _STL_DISABLED_WARNING_C4577 4577 +#endif // _HAS_EXCEPTIONS + +// warning C4984: 'if constexpr' is a C++17 language extension +#if !_HAS_CXX17 && _HAS_IF_CONSTEXPR +#define _STL_DISABLED_WARNING_C4984 4984 +#else // !_HAS_CXX17 && _HAS_IF_CONSTEXPR +#define _STL_DISABLED_WARNING_C4984 +#endif // !_HAS_CXX17 && _HAS_IF_CONSTEXPR + +// warning C5053: support for 'explicit()' in C++17 and earlier is a vendor extension +#if !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT +#define _STL_DISABLED_WARNING_C5053 5053 +#else // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT +#define _STL_DISABLED_WARNING_C5053 +#endif // !_HAS_CXX20 && _HAS_CONDITIONAL_EXPLICIT + +#ifndef _STL_EXTRA_DISABLED_WARNINGS +#define _STL_EXTRA_DISABLED_WARNINGS +#endif // _STL_EXTRA_DISABLED_WARNINGS + +// warning C4180: qualifier applied to function type has no meaning; ignored +// warning C4412: function signature contains type 'meow'; C++ objects are unsafe to pass between pure code +// and mixed or native. (/Wall) +// warning C4455: literal suffix identifiers that do not start with an underscore are reserved +// warning C4472: 'meow' is a native enum: add an access specifier (private/public) +// to declare a managed enum (/Wall) +// warning C4494: Ignoring __declspec(allocator) because the function return type is not a pointer or reference +// warning C4514: unreferenced inline function has been removed (/Wall) +// warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; +// structured exceptions (SEH) are no longer caught (/Wall) +// warning C4574: 'MACRO' is defined to be '0': did you mean to use '#if MACRO'? (/Wall) +// warning C4582: 'union': constructor is not implicitly called (/Wall) +// warning C4583: 'union': destructor is not implicitly called (/Wall) +// warning C4587: behavior change: constructor is no longer implicitly called (/Wall) +// warning C4588: behavior change: destructor is no longer implicitly called (/Wall) +// warning C4619: #pragma warning: there is no warning number 'number' (/Wall) +// warning C4623: default constructor was implicitly defined as deleted (/Wall) +// warning C4625: copy constructor was implicitly defined as deleted (/Wall) +// warning C4626: assignment operator was implicitly defined as deleted (/Wall) +// warning C4643: Forward declaring 'meow' in namespace std is not permitted by the C++ Standard. (/Wall) +// warning C4702: unreachable code +// warning C4793: function compiled as native +// warning C4820: 'N' bytes padding added after data member 'meow' (/Wall) +// warning C4988: variable declared outside class/function scope (/Wall /d1WarnOnGlobals) +// warning C5026: move constructor was implicitly defined as deleted (/Wall) +// warning C5027: move assignment operator was implicitly defined as deleted (/Wall) +// warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified (/Wall) + +#ifndef _STL_DISABLED_WARNINGS +// clang-format off +#define _STL_DISABLED_WARNINGS \ + 4180 4412 4455 4472 4494 4514 4571 4574 4582 4583 \ + 4587 4588 4619 4623 4625 4626 4643 4702 4793 4820 \ + 4988 5026 5027 5045 \ + _STL_DISABLED_WARNING_C4577 \ + _STL_DISABLED_WARNING_C4984 \ + _STL_DISABLED_WARNING_C5053 \ + _STL_EXTRA_DISABLED_WARNINGS +// clang-format on +#endif // _STL_DISABLED_WARNINGS + +// warning: constexpr if is a C++17 extension [-Wc++17-extensions] +// warning: user-defined literal suffixes not starting with '_' are reserved [-Wuser-defined-literals] +// warning: unknown pragma ignored [-Wunknown-pragmas] +#ifndef _STL_DISABLE_CLANG_WARNINGS +#ifdef __clang__ +// clang-format off +#define _STL_DISABLE_CLANG_WARNINGS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \ + _Pragma("clang diagnostic ignored \"-Wuser-defined-literals\"") \ + _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +// clang-format on +#else // __clang__ +#define _STL_DISABLE_CLANG_WARNINGS +#endif // __clang__ +#endif // _STL_DISABLE_CLANG_WARNINGS + +#ifndef _STL_RESTORE_CLANG_WARNINGS +#ifdef __clang__ +#define _STL_RESTORE_CLANG_WARNINGS _Pragma("clang diagnostic pop") +#else // __clang__ +#define _STL_RESTORE_CLANG_WARNINGS +#endif // __clang__ +#endif // _STL_RESTORE_CLANG_WARNINGS + +// clang-format off +#ifndef _STL_DISABLE_DEPRECATED_WARNING +#ifdef __clang__ +#define _STL_DISABLE_DEPRECATED_WARNING \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#else // __clang__ +#define _STL_DISABLE_DEPRECATED_WARNING \ + __pragma(warning(push)) \ + __pragma(warning(disable : 4996)) // was declared deprecated +#endif // __clang__ +#endif // _STL_DISABLE_DEPRECATED_WARNING +// clang-format on + +#ifndef _STL_RESTORE_DEPRECATED_WARNING +#ifdef __clang__ +#define _STL_RESTORE_DEPRECATED_WARNING _Pragma("clang diagnostic pop") +#else // __clang__ +#define _STL_RESTORE_DEPRECATED_WARNING __pragma(warning(pop)) +#endif // __clang__ +#endif // _STL_RESTORE_DEPRECATED_WARNING + +#define _CPPLIB_VER 650 +#define _MSVC_STL_VERSION 142 +#define _MSVC_STL_UPDATE 201912L + +#ifndef _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH +#ifdef __EDG__ +// not attempting to detect __EDG_VERSION__ being less than expected +#elif defined(__clang__) +#if __clang_major__ < 9 +#error STL1000: Unexpected compiler version, expected Clang 9.0.0 or newer. +#endif // ^^^ old Clang ^^^ +#elif defined(_MSC_VER) +#if _MSC_VER < 1924 // Coarse-grained, not inspecting _MSC_FULL_VER +#error STL1001: Unexpected compiler version, expected MSVC 19.24 or newer. +#endif // ^^^ old MSVC ^^^ +#else // vvv other compilers vvv +// not attempting to detect other compilers +#endif // ^^^ other compilers ^^^ +#endif // _ALLOW_COMPILER_AND_STL_VERSION_MISMATCH + +#ifndef _HAS_STATIC_RTTI +#define _HAS_STATIC_RTTI 1 +#endif // _HAS_STATIC_RTTI + +#if defined(_CPPRTTI) && !_HAS_STATIC_RTTI +#error /GR implies _HAS_STATIC_RTTI. +#endif // defined(_CPPRTTI) && !_HAS_STATIC_RTTI + +// C++17 constexpr additions +#if _HAS_CXX17 +#define _CONSTEXPR17 constexpr +#else // ^^^ has C++17 constexpr additions / no C++17 constexpr additions vvv +#define _CONSTEXPR17 inline +#endif // _HAS_CXX17 + +// P0607R0 Inline Variables For The STL +#if _HAS_CXX17 +#define _INLINE_VAR inline +#else // _HAS_CXX17 +#define _INLINE_VAR +#endif // _HAS_CXX17 + +// N4190 Removing auto_ptr, random_shuffle(), And Old Stuff +#ifndef _HAS_AUTO_PTR_ETC +#define _HAS_AUTO_PTR_ETC (!_HAS_CXX17) +#endif // _HAS_AUTO_PTR_ETC + +// P0003R5 Removing Dynamic Exception Specifications +#ifndef _HAS_UNEXPECTED +#define _HAS_UNEXPECTED (!_HAS_CXX17) +#endif // _HAS_UNEXPECTED + +// P0004R1 Removing Deprecated Iostreams Aliases +#ifndef _HAS_OLD_IOSTREAMS_MEMBERS +#define _HAS_OLD_IOSTREAMS_MEMBERS (!_HAS_CXX17) +#endif // _HAS_OLD_IOSTREAMS_MEMBERS + +// P0298R3 std::byte +#ifndef _HAS_STD_BYTE +#define _HAS_STD_BYTE _HAS_CXX17 // inspected by GSL, do not remove +#endif // _HAS_STD_BYTE + +// P0302R1 Removing Allocator Support In std::function +// LWG-2385 function::assign allocator argument doesn't make sense +// LWG-2921 packaged_task and type-erased allocators +// LWG-2976 Dangling uses_allocator specialization for packaged_task +#ifndef _HAS_FUNCTION_ALLOCATOR_SUPPORT +#define _HAS_FUNCTION_ALLOCATOR_SUPPORT (!_HAS_CXX17) +#endif // _HAS_FUNCTION_ALLOCATOR_SUPPORT + +// The non-Standard std::tr1 namespace and TR1-only machinery +#ifndef _HAS_TR1_NAMESPACE +#define _HAS_TR1_NAMESPACE (!_HAS_CXX17) +#endif // _HAS_TR1_NAMESPACE + +// STL4000 is "_STATIC_CPPLIB is deprecated", currently in yvals.h +// STL4001 is "/clr:pure is deprecated", currently in yvals.h + +#if _HAS_TR1_NAMESPACE +#ifdef _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING +#define _DEPRECATE_TR1_NAMESPACE +#else // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING +#define _DEPRECATE_TR1_NAMESPACE \ + [[deprecated( \ + "warning STL4002: " \ + "The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED. You can " \ + "define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING to acknowledge that you have received this warning.")]] +#endif // _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING +#endif // _HAS_TR1_NAMESPACE + +// STL4003 was "The non-Standard std::identity struct is deprecated and will be REMOVED." + +// Enforcement of matching allocator value_types +#ifndef _ENFORCE_MATCHING_ALLOCATORS +#define _ENFORCE_MATCHING_ALLOCATORS _HAS_CXX17 +#endif // _ENFORCE_MATCHING_ALLOCATORS + +#define _MISMATCHED_ALLOCATOR_MESSAGE(_CONTAINER, _VALUE_TYPE) \ + _CONTAINER " requires that Allocator's value_type match " _VALUE_TYPE \ + " (See N4659 26.2.1 [container.requirements.general]/16 allocator_type)" \ + " Either fix the allocator value_type or define _ENFORCE_MATCHING_ALLOCATORS=0" \ + " to suppress this diagnostic." + +// Enforcement of Standard facet specializations +#ifndef _ENFORCE_FACET_SPECIALIZATIONS +#define _ENFORCE_FACET_SPECIALIZATIONS 0 +#endif // _ENFORCE_FACET_SPECIALIZATIONS + +#define _FACET_SPECIALIZATION_MESSAGE \ + "Unsupported facet specialization; see N4800 27.3.1.1.1 [locale.category]. " \ + "Either use a Standard specialization or define _ENFORCE_FACET_SPECIALIZATIONS=0 " \ + "to suppress this diagnostic." + +// To improve compiler throughput, use 'hidden friend' operators in instead of non-members that are +// depicted in the Standard. +#ifndef _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS +#define _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS 1 +#endif // _STL_OPTIMIZE_SYSTEM_ERROR_OPERATORS + +#if _HAS_IF_CONSTEXPR +#define _CONSTEXPR_IF constexpr +#else // _HAS_IF_CONSTEXPR +#define _CONSTEXPR_IF +#endif // _HAS_IF_CONSTEXPR + +#ifdef __clang__ +#define _CONSTEVAL consteval +#else // ^^^ supports consteval / no consteval vvv +#define _CONSTEVAL constexpr +#endif // ^^^ no consteval ^^^ + +// Controls whether the STL will force /fp:fast to enable vectorization of algorithms defined +// in the standard as special cases; such as reduce, transform_reduce, inclusive_scan, exclusive_scan +#ifndef _STD_VECTORIZE_WITH_FLOAT_CONTROL +#ifdef _M_FP_EXCEPT +#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 0 +#else // ^^^ floating point exceptions enabled / floating point exceptions disabled (default) vvv +#define _STD_VECTORIZE_WITH_FLOAT_CONTROL 1 +#endif // _M_FP_EXCEPT +#endif // _STD_VECTORIZE_WITH_FLOAT_CONTROL + +// P0174R2 Deprecating Vestigial Library Parts +// P0521R0 Deprecating shared_ptr::unique() +// Other C++17 deprecation warnings + +// N4659 D.4 [depr.cpp.headers] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_C_HEADER \ + [[deprecated("warning STL4004: " \ + ", , , and are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_C_HEADER_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_C_HEADER +#endif // ^^^ warning disabled ^^^ + +// N4659 D.6 [depr.str.strstreams] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_STRSTREAM \ + [[deprecated("warning STL4005: is deprecated in C++17. " \ + "You can define _SILENCE_CXX17_STRSTREAM_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_STRSTREAM +#endif // ^^^ warning disabled ^^^ + +// N4659 D.7 [depr.uncaught] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION \ + [[deprecated("warning STL4006: " \ + "std::uncaught_exception() is deprecated in C++17. " \ + "It is superseded by std::uncaught_exceptions(), plural. " \ + "You can define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_UNCAUGHT_EXCEPTION +#endif // ^^^ warning disabled ^^^ + +// N4659 D.8.1 [depr.weak.result_type] +// N4659 D.8.2 [depr.func.adaptor.typedefs] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS \ + [[deprecated( \ + "warning STL4007: Many result_type typedefs " \ + "and all argument_type, first_argument_type, and second_argument_type typedefs are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_ADAPTOR_TYPEDEFS +#endif // ^^^ warning disabled ^^^ + +// N4659 D.8.3 [depr.negators] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_NEGATORS \ + [[deprecated("warning STL4008: " \ + "std::not1(), std::not2(), std::unary_negate, and std::binary_negate are deprecated in C++17. " \ + "They are superseded by std::not_fn(). " \ + "You can define _SILENCE_CXX17_NEGATORS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_NEGATORS +#endif // ^^^ warning disabled ^^^ + +// STL4009 was "std::allocator is deprecated in C++17" + +// N4659 D.9 [depr.default.allocator] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS \ + [[deprecated("warning STL4010: " \ + "Various members of std::allocator are deprecated in C++17. " \ + "Use std::allocator_traits instead of accessing these members directly. " \ + "You can define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS +#endif // ^^^ warning disabled ^^^ + +// N4659 D.10 [depr.storage.iterator] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR \ + [[deprecated("warning STL4011: " \ + "std::raw_storage_iterator is deprecated in C++17. " \ + "Consider using the std::uninitialized_copy() family of algorithms instead. " \ + "You can define _SILENCE_CXX17_RAW_STORAGE_ITERATOR_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_RAW_STORAGE_ITERATOR +#endif // ^^^ warning disabled ^^^ + +// N4659 D.11 [depr.temporary.buffer] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_TEMPORARY_BUFFER \ + [[deprecated("warning STL4012: " \ + "std::get_temporary_buffer() and std::return_temporary_buffer() are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_TEMPORARY_BUFFER_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_TEMPORARY_BUFFER +#endif // ^^^ warning disabled ^^^ + +// N4659 D.12 [depr.meta.types] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_IS_LITERAL_TYPE \ + [[deprecated("warning STL4013: " \ + "std::is_literal_type and std::is_literal_type_v are deprecated in C++17. " \ + "You can define _SILENCE_CXX17_IS_LITERAL_TYPE_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_IS_LITERAL_TYPE +#endif // ^^^ warning disabled ^^^ + +// N4659 D.12 [depr.meta.types] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_RESULT_OF \ + [[deprecated("warning STL4014: " \ + "std::result_of and std::result_of_t are deprecated in C++17. " \ + "They are superseded by std::invoke_result and std::invoke_result_t. " \ + "You can define _SILENCE_CXX17_RESULT_OF_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_RESULT_OF +#endif // ^^^ warning disabled ^^^ + +// N4659 D.13 [depr.iterator.primitives] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS \ + [[deprecated( \ + "warning STL4015: " \ + "The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. " \ + "(The header is NOT deprecated.) The C++ Standard has never required user-defined iterators to " \ + "derive from std::iterator. To fix this warning, stop deriving from std::iterator and start providing " \ + "publicly accessible typedefs named iterator_category, value_type, difference_type, pointer, and reference. " \ + "Note that value_type is required to be non-const, even for constant iterators. " \ + "You can define _SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_ITERATOR_BASE_CLASS +#endif // ^^^ warning disabled ^^^ + +// N4659 D.14 [depr.util.smartptr.shared.obs] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE \ + [[deprecated("warning STL4016: " \ + "std::shared_ptr::unique() is deprecated in C++17. " \ + "You can define _SILENCE_CXX17_SHARED_PTR_UNIQUE_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_SHARED_PTR_UNIQUE +#endif // ^^^ warning disabled ^^^ + +// N4659 D.15 [depr.locale.stdcvt] +// N4659 D.16 [depr.conversions] +#if _HAS_CXX17 && !defined(_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS) +#define _CXX17_DEPRECATE_CODECVT_HEADER \ + [[deprecated( \ + "warning STL4017: " \ + "std::wbuffer_convert, std::wstring_convert, and the header (containing std::codecvt_mode, " \ + "std::codecvt_utf8, std::codecvt_utf16, and std::codecvt_utf8_utf16) are deprecated in C++17. " \ + "(The std::codecvt class template is NOT deprecated.) " \ + "The C++ Standard doesn't provide equivalent non-deprecated functionality; " \ + "consider using MultiByteToWideChar() and WideCharToMultiByte() from instead. " \ + "You can define _SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX17_DEPRECATE_CODECVT_HEADER +#endif // ^^^ warning disabled ^^^ + +// STL4018 was "The non-Standard std::tr2::sys namespace is deprecated and will be REMOVED." + +#ifdef _SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING +#define _DEPRECATE_FPOS_SEEKPOS +#else // ^^^ warning disabled / warning enabled vvv +#define _DEPRECATE_FPOS_SEEKPOS \ + [[deprecated("warning STL4019: " \ + "The member std::fpos::seekpos() is non-Standard, and is preserved only for compatibility with " \ + "workarounds for old versions of Visual C++. It will be removed in a future release, and in this " \ + "release always returns 0. Please use standards-conforming mechanisms to manipulate fpos, such as " \ + "conversions to and from streamoff, or an integral type, instead. If you are receiving this message " \ + "while compiling Boost.IOStreams, a fix has been submitted upstream to make Boost use " \ + "standards-conforming mechanisms, as it does for other compilers. You can define " \ + "_SILENCE_FPOS_SEEKPOS_DEPRECATION_WARNING to acknowledge that you have received this warning, " \ + "or define _REMOVE_FPOS_SEEKPOS to remove std::fpos::seekpos entirely.")]] +#endif // ^^^ warning enabled ^^^ + +// P0482R6 Library Support For char8_t +// Other C++20 deprecation warnings + +// N4810 D.16 [depr.locale.category] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_CODECVT_FACETS \ + [[deprecated("warning STL4020: " \ + "std::codecvt, std::codecvt, " \ + "std::codecvt_byname, and std::codecvt_byname " \ + "are deprecated in C++20 and replaced by specializations with a second argument of type char8_t. " \ + "You can define _SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_CODECVT_FACETS +#endif // ^^^ warning disabled ^^^ + +// N4810 D.17 [depr.fs.path.factory] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_U8PATH_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_U8PATH \ + [[deprecated("warning STL4021: " \ + "The std::filesystem::u8path() overloads are deprecated in C++20. " \ + "The constructors of std::filesystem::path provide equivalent functionality via construction from " \ + "u8string, u8string_view, or iterators with value_type char8_t." \ + "You can define _SILENCE_CXX20_U8PATH_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_U8PATH +#endif // ^^^ warning disabled ^^^ + +#if !defined(_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING) +#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND \ + [[deprecated( \ + "warning STL4022: " \ + "The hash_meow and unordered_meow containers' non-Standard lower_bound() member was provided for interface " \ + "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ + "hash_meow or unordered_meow containers. Please use the find() member instead. You can define " \ + "_SILENCE_STDEXT_HASH_LOWER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_STDEXT_HASH_LOWER_BOUND +#endif // ^^^ warning disabled ^^^ + +#if !defined(_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING) +#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND \ + [[deprecated( \ + "warning STL4023: " \ + "The hash_meow and unordered_meow containers' non-Standard upper_bound() member was provided for interface " \ + "compatibility with the ordered associative containers, and doesn't match the semantics of the " \ + "hash_meow or unordered_meow containers. Please use the second iterator returned by the " \ + "equal_range() member instead. You can define " \ + "_SILENCE_STDEXT_HASH_UPPER_BOUND_DEPRECATION_WARNING to suppress this deprecation.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_STDEXT_HASH_UPPER_BOUND +#endif // ^^^ warning disabled ^^^ + +// P0966R1 [depr.string.capacity] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT \ + [[deprecated("warning STL4024: " \ + "std::string::reserve() without an argument is deprecated in C++20. " \ + "To shrink the string's capacity, use std::string::shrink_to_fit() instead. Otherwise, provide an " \ + "argument to std::string::reserve(). " \ + "You can define _SILENCE_CXX20_STRING_RESERVE_WITHOUT_ARGUMENT_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_STRING_RESERVE_WITHOUT_ARGUMENT +#endif // ^^^ warning disabled ^^^ + +// P0767R1 [depr.meta.types] +#if _HAS_CXX20 && !defined(_SILENCE_CXX20_IS_POD_DEPRECATION_WARNING) \ + && !defined(_SILENCE_ALL_CXX20_DEPRECATION_WARNINGS) +#define _CXX20_DEPRECATE_IS_POD \ + [[deprecated("warning STL4025: " \ + "std::is_pod and std::is_pod_v are deprecated in C++20. " \ + "The std::is_trivially_copyable and/or std::is_standard_layout traits likely suit your use case. " \ + "You can define _SILENCE_CXX20_IS_POD_DEPRECATION_WARNING " \ + "or _SILENCE_ALL_CXX20_DEPRECATION_WARNINGS to acknowledge that you have received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _CXX20_DEPRECATE_IS_POD +#endif // ^^^ warning disabled ^^^ + +#if _HAS_CXX20 && !defined(_SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING) +#define _DEPRECATE_EXPERIMENTAL_ERASE \ + [[deprecated("warning STL4026: " \ + "std::experimental::erase() and std::experimental::erase_if() are deprecated by Microsoft and will " \ + "be REMOVED. They are superseded by std::erase() and std::erase_if(). " \ + "You can define _SILENCE_EXPERIMENTAL_ERASE_DEPRECATION_WARNING to acknowledge that you have " \ + "received this warning.")]] +#else // ^^^ warning enabled / warning disabled vvv +#define _DEPRECATE_EXPERIMENTAL_ERASE +#endif // ^^^ warning disabled ^^^ + +// next warning number: STL4027 + + +// LIBRARY FEATURE-TEST MACROS + +// C++14 +#define __cpp_lib_chrono_udls 201304L +#define __cpp_lib_complex_udls 201309L +#define __cpp_lib_exchange_function 201304L +#define __cpp_lib_generic_associative_lookup 201304L +#define __cpp_lib_integer_sequence 201304L +#define __cpp_lib_integral_constant_callable 201304L +#define __cpp_lib_is_final 201402L +#define __cpp_lib_is_null_pointer 201309L +#define __cpp_lib_make_reverse_iterator 201402L +#define __cpp_lib_make_unique 201304L +#define __cpp_lib_null_iterators 201304L +#define __cpp_lib_quoted_string_io 201304L +#define __cpp_lib_result_of_sfinae 201210L +#define __cpp_lib_robust_nonmodifying_seq_ops 201304L +#ifndef _M_CEE +#define __cpp_lib_shared_timed_mutex 201402L +#endif // _M_CEE +#define __cpp_lib_string_udls 201304L +#define __cpp_lib_transformation_trait_aliases 201304L +#define __cpp_lib_tuple_element_t 201402L +#define __cpp_lib_tuples_by_type 201304L + +// C++17 +#define __cpp_lib_addressof_constexpr 201603L +#define __cpp_lib_allocator_traits_is_always_equal 201411L +#define __cpp_lib_as_const 201510L +#define __cpp_lib_bool_constant 201505L +#define __cpp_lib_enable_shared_from_this 201603L +#define __cpp_lib_incomplete_container_elements 201505L +#define __cpp_lib_invoke 201411L +#define __cpp_lib_logical_traits 201510L +#define __cpp_lib_map_try_emplace 201411L +#define __cpp_lib_nonmember_container_access 201411L +#define __cpp_lib_shared_mutex 201505L + +#ifdef __cpp_concepts +#define __cpp_lib_shared_ptr_arrays 201707L +#else // __cpp_concepts +#define __cpp_lib_shared_ptr_arrays 201611L +#endif // __cpp_concepts + +#define __cpp_lib_transparent_operators 201510L +#define __cpp_lib_type_trait_variable_templates 201510L +#define __cpp_lib_uncaught_exceptions 201411L +#define __cpp_lib_unordered_map_try_emplace 201411L +#define __cpp_lib_void_t 201411L + +#if _HAS_CXX17 +#define __cpp_lib_any 201606L +#define __cpp_lib_apply 201603L +#define __cpp_lib_array_constexpr 201803L +#define __cpp_lib_atomic_is_always_lock_free 201603L +#define __cpp_lib_boyer_moore_searcher 201603L +#if _HAS_STD_BYTE +#define __cpp_lib_byte 201603L +#endif // _HAS_STD_BYTE +#define __cpp_lib_chrono 201611L +#define __cpp_lib_clamp 201603L +#ifndef _M_CEE +#define __cpp_lib_execution 201603L +#endif // _M_CEE +#define __cpp_lib_filesystem 201703L +#define __cpp_lib_gcd_lcm 201606L +#define __cpp_lib_hardware_interference_size 201703L +#define __cpp_lib_has_unique_object_representations 201606L +#define __cpp_lib_hypot 201603L +#define __cpp_lib_is_aggregate 201703L +#define __cpp_lib_is_invocable 201703L +#define __cpp_lib_is_swappable 201603L +#define __cpp_lib_launder 201606L +#define __cpp_lib_make_from_tuple 201606L +#define __cpp_lib_math_special_functions 201603L +#define __cpp_lib_memory_resource 201603L +#define __cpp_lib_node_extract 201606L +#define __cpp_lib_not_fn 201603L +#define __cpp_lib_optional 201606L +#ifndef _M_CEE +#define __cpp_lib_parallel_algorithm 201603L +#endif // _M_CEE +#define __cpp_lib_raw_memory_algorithms 201606L +#define __cpp_lib_sample 201603L +#define __cpp_lib_scoped_lock 201703L +#define __cpp_lib_shared_ptr_weak_type 201606L +#define __cpp_lib_string_view 201803L +#define __cpp_lib_to_chars 201611L +#define __cpp_lib_variant 201606L +#else // _HAS_CXX17 +#define __cpp_lib_chrono 201510L +#endif // _HAS_CXX17 + +// C++20 +#if _HAS_CXX20 +#define __cpp_lib_atomic_float 201711L +#define __cpp_lib_bind_front 201907L + +#if defined(__clang__) || defined(__EDG__) +#define __cpp_lib_bitops 201907L +#else // ^^^ Clang and EDG / MSVC vvv +// a future MSVC update will embed CPU feature detection into intrinsics +// TRANSITION, VSO-1020212 +#endif // defined(__clang__) || defined(__EDG__) + +#define __cpp_lib_bounded_array_traits 201902L + +#ifdef __cpp_char8_t +#define __cpp_lib_char8_t 201811L +#endif // __cpp_char8_t + +#if defined(__cpp_concepts) && __cpp_concepts > 201507L +#define __cpp_lib_concepts 201907L + +// P0898R3 (as modified by P1754R1) std::boolean +#ifndef _HAS_STD_BOOLEAN +#define _HAS_STD_BOOLEAN 1 +#endif // _HAS_STD_BOOLEAN +#endif // defined(__cpp_concepts) && __cpp_concepts > 201507L + +#define __cpp_lib_endian 201907L +#define __cpp_lib_erase_if 201811L +#define __cpp_lib_generic_unordered_lookup 201811L +#define __cpp_lib_int_pow2 201806L + +#if defined(__clang__) || defined(__EDG__) || (defined(_MSC_VER) && _MSC_VER >= 1925) +#define __cpp_lib_is_constant_evaluated 201811L +#endif // TRANSITION, VS 2019 16.5 Preview 2 + +#define __cpp_lib_list_remove_return_type 201806L +#define __cpp_lib_math_constants 201907L +#define __cpp_lib_nothrow_convertible 201806L +#define __cpp_lib_remove_cvref 201711L +#define __cpp_lib_shift 201806L +#define __cpp_lib_ssize 201902L +#define __cpp_lib_starts_ends_with 201711L +#define __cpp_lib_to_address 201711L +#define __cpp_lib_to_array 201907L +#define __cpp_lib_type_identity 201806L +#define __cpp_lib_unwrap_ref 201811L +#endif // _HAS_CXX20 + +// EXPERIMENTAL +#define __cpp_lib_experimental_erase_if 201411L +#define __cpp_lib_experimental_filesystem 201406L + + +#ifdef _RTC_CONVERSION_CHECKS_ENABLED +#ifndef _ALLOW_RTCc_IN_STL +#error /RTCc rejects conformant code, so it is not supported by the C++ Standard Library. Either remove this \ +compiler option, or define _ALLOW_RTCc_IN_STL to acknowledge that you have received this warning. +#endif // _ALLOW_RTCc_IN_STL +#endif // _RTC_CONVERSION_CHECKS_ENABLED + +#ifndef _DECLSPEC_ALLOCATOR +#ifdef __clang__ +#define _DECLSPEC_ALLOCATOR +#else // ^^^ Clang / non-Clang vvv +#define _DECLSPEC_ALLOCATOR __declspec(allocator) +#endif // ^^^ non-Clang ^^^ +#endif // _DECLSPEC_ALLOCATOR + +#define _STRINGIZEX(x) #x +#define _STRINGIZE(x) _STRINGIZEX(x) +#define _EMPTY_ARGUMENT // for empty macro argument + +// NAMESPACE +#define _STD_BEGIN namespace std { +#define _STD_END } +#define _STD ::std:: +#define _RANGES ::std::ranges:: + +// We use the stdext (standard extension) namespace to contain extensions that are not part of the current standard +#define _STDEXT_BEGIN namespace stdext { +#define _STDEXT_END } +#define _STDEXT ::stdext:: + +#ifdef __cplusplus +#define _CSTD :: + +#define _EXTERN_C extern "C" { +#define _END_EXTERN_C } +#else // ^^^ __cplusplus / !__cplusplus vvv +#define _CSTD + +#define _EXTERN_C +#define _END_EXTERN_C +#endif // __cplusplus + +#ifdef _M_CEE_PURE +#define _EXTERN_C_UNLESS_PURE +#define _END_EXTERN_C_UNLESS_PURE +#define _STATIC_UNLESS_PURE // Avoid warning C4640: construction of local static object is not thread-safe (/Wall) +#else // ^^^ _M_CEE_PURE / !_M_CEE_PURE vvv +#define _EXTERN_C_UNLESS_PURE _EXTERN_C +#define _END_EXTERN_C_UNLESS_PURE _END_EXTERN_C +#define _STATIC_UNLESS_PURE static +#endif // _M_CEE_PURE + +#if defined(MRTDLL) && !defined(_CRTBLD) +#error In yvals_core.h, defined(MRTDLL) implies defined(_CRTBLD); !defined(_CRTBLD) implies !defined(MRTDLL) +#endif // defined(MRTDLL) && !defined(_CRTBLD) + +#if defined(MRTDLL) && !defined(_M_CEE_PURE) +#error In yvals_core.h, defined(MRTDLL) implies defined(_M_CEE_PURE); !defined(_M_CEE_PURE) implies !defined(MRTDLL) +#endif // defined(MRTDLL) && !defined(_M_CEE_PURE) + +#endif // _STL_COMPILER_PREPROCESSOR +#endif // _YVALS_CORE_H_ From e2ba89b3cef534ba46c85b6e9cf1b15018e5b16c Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Sat, 14 Dec 2019 14:00:36 +0100 Subject: [PATCH 19/52] Optimize for trivially destructible types --- stl/inc/memory | 53 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index e2b5359bec0..3048dfd27ca 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1690,9 +1690,9 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, } // CLASS TEMPLATE _Ref_count_unbounded_array -template -class _Ref_count_unbounded_array - : public _Ref_count_base { // handle reference counting for unbounded array in control block, no allocator +template >> +class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array with + // non-trivial destruction in control block, no allocator public: explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); @@ -1725,6 +1725,39 @@ private: } }; +template +class _Ref_count_unbounded_array<_Ty, true> : public _Ref_count_base { // handle reference counting for unbounded array + // with trivial destruction in control block, + // no allocator +public: + explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { + _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Count); + } + + explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) : _Ref_count_base() { + _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Count, _Val); + } + + ~_Ref_count_unbounded_array() = default; // nothing to do, _Ty is trivially destructible + + auto _Get_ptr() { + return reinterpret_cast*>( + reinterpret_cast(this) + _Div_ceil(sizeof(*this), alignof(_Ty)) * alignof(_Ty)); + } + +private: + virtual void _Destroy() noexcept override { // destroy managed resource + // nothing to do, _Ty is trivially destructible + } + + virtual void _Delete_this() noexcept override { // destroy self + using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), + _Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + this->~_Ref_count_unbounded_array(); + delete[] reinterpret_cast<_Storage*>(this); + } +}; + // CLASS TEMPLATE _Ref_count_bounded_array template class _Ref_count_bounded_array @@ -1965,7 +1998,7 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si // CLASS TEMPLATE _Ref_count_unbounded_array_alloc template class __declspec(empty_bases) _Ref_count_unbounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { - // handle reference counting for object in control block, allocator + // handle reference counting for unbounded array in control block, allocator public: explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, const size_t _Count) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { @@ -1991,8 +2024,10 @@ private: ~_Ref_count_unbounded_array_alloc() = default; // nothing to do; _Storage._Value already destroyed by _Destroy() virtual void _Destroy() noexcept override { // destroy managed resource - _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); - _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); + if constexpr (!is_trivially_destructible_v>) { + _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); + } } virtual void _Delete_this() noexcept override { // destroy self @@ -2033,8 +2068,10 @@ private: } virtual void _Destroy() noexcept override { // destroy managed resource - _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); - _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); + if constexpr (!is_trivially_destructible_v<_Ty>) { + _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); + } } virtual void _Delete_this() noexcept override { // destroy self From f64bfb0d8cd4d29da3a34b0d83c2ab8558f13cac Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Wed, 29 Jan 2020 18:36:57 +0100 Subject: [PATCH 20/52] Mainly readability improvements --- stl/inc/memory | 196 +++++++++++++++++++++++-------------------------- 1 file changed, 90 insertions(+), 106 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 3048dfd27ca..b008f16b6e7 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1252,16 +1252,12 @@ private: _Owner._Call_deleter = false; } +#ifdef __cpp_concepts // clang-format off template -#ifdef __cpp_concepts requires (!is_array_v<_Ty0>) -#endif // __cpp_concepts friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); - // clang-format on -#ifdef __cpp_concepts - // clang-format off template requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(const size_t _Count); @@ -1277,19 +1273,11 @@ private: template requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); - // clang-format on -#endif // __cpp_concepts - // clang-format off template -#ifdef __cpp_concepts requires (!is_array_v<_Ty0>) -#endif // __cpp_concepts friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); - // clang-format on - -#ifdef __cpp_concepts - // clang-format off + template requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const size_t _Count); @@ -1307,7 +1295,13 @@ private: requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); // clang-format on -#endif // __cpp_concepts +#else // ^^^ __cpp_concepts / !__cpp_concepts vvv + template + friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); + + template + friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); +#endif // !__cpp_concepts template void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px @@ -1559,7 +1553,9 @@ private: #ifdef __cpp_concepts template constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { - return (_Val1 % _Val2 == 0) ? (_Val1 / _Val2) : (_Val1 / _Val2 + 1); + using _Signed = make_signed_t<_Ty>; + const auto _Res = _STD div(_Signed(_Val1), _Signed(_Val2)); + return (_Res.rem == 0) ? (_Res.quot) : (_Res.quot + 1); } template @@ -1576,11 +1572,9 @@ struct _Uninitialized_rev_destroying_backout { // struct to undo partially const _Uninitialized_rev_destroying_backout& operator=(const _Uninitialized_rev_destroying_backout&) = delete; ~_Uninitialized_rev_destroying_backout() { - if (_Last != _First) { - do { - --_Last; - _STD destroy_at(_Last); - } while (_Last != _First); + while (_Last != _First) { + --_Last; + _STD destroy_at(_Last); } } @@ -1597,18 +1591,15 @@ struct _Uninitialized_rev_destroying_backout { // struct to undo partially const }; template -void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, const size_t _Size) { - if (_Size != 0) { - size_t _Idx = _Size; - do { - --_Idx; - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { - _Reverse_destroy_multidimensional_n(_Arr[_Idx], extent_v<_Ty>); - } else { - _Destroy_in_place(_Arr[_Idx]); - } - } while (_Idx > 0); +void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) { + while (_Size > 0) { + --_Size; + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { + _Reverse_destroy_multidimensional_n(_Arr[_Size], extent_v<_Ty>); + } else { + _Destroy_in_place(_Arr[_Size]); + } } } @@ -1624,16 +1615,16 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ _RERAISE; _CATCH_END } - } else { - if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { + } else if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { + if (0 < _Size) { _Copy_memmove(_In, _In + _Size, _Out); - } else { - _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Backout._Emplace_back(_In[_Idx]); - } - _Backout._Release(); } + } else { + _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _Backout._Emplace_back(_In[_Idx]); + } + _Backout._Release(); } } @@ -1649,16 +1640,16 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si _RERAISE; _CATCH_END } - } else { - if constexpr (_Use_memset_value_construct_v<_Ty*>) { + } else if constexpr (_Use_memset_value_construct_v<_Ty*>) { + if (0 < _Size) { _Zero_range(_Out, _Out + _Size); - } else { - _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { - _Backout._Emplace_back(); - } - _Backout._Release(); } + } else { + _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(); + } + _Backout._Release(); } } @@ -1674,18 +1665,16 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, _RERAISE; _CATCH_END } - } else { + } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { if (0 < _Size) { - if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { - _CSTD memset(_Out, static_cast(_Val), _Size); - } else { - _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { - _Backout._Emplace_back(_Val); - } - _Backout._Release(); - } + _CSTD memset(_Out, static_cast(_Val), _Size); + } + } else { + _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(_Val); } + _Backout._Release(); } } @@ -1875,11 +1864,9 @@ public: _Uninitialized_rev_destroying_backout_al& operator=(const _Uninitialized_rev_destroying_backout_al&) = delete; ~_Uninitialized_rev_destroying_backout_al() { - if (_Last != _First) { - do { - --_Last; - allocator_traits<_Alloc>::destroy(_Al, _Last); - } while (_Last != _First); + while (_Last != _First) { + --_Last; + allocator_traits<_Alloc>::destroy(_Al, _Last); } } @@ -1901,18 +1888,15 @@ private: }; template -void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, const size_t _Size, _Alloc& _Al) { - if (_Size != 0) { - size_t _Idx = _Size; - do { - --_Idx; - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { - _Reverse_destroy_multidimensional_n_al(_Arr[_Idx], extent_v<_Ty>, _Al); - } else { - allocator_traits<_Alloc>::destroy(_Al, _Arr + _Idx); - } - } while (_Idx > 0); +void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Alloc& _Al) { + while (_Size > 0) { + --_Size; + // TRANSITION, LLVM-42404 + if constexpr ((rank_v<_Ty>) > 0) { + _Reverse_destroy_multidimensional_n_al(_Arr[_Size], extent_v<_Ty>, _Al); + } else { + allocator_traits<_Alloc>::destroy(_Al, _Arr + _Size); + } } } @@ -1928,18 +1912,18 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out _RERAISE; _CATCH_END } - } else { - if constexpr (conjunction_v::_Really_trivial>, - _Uses_default_construct<_Alloc, _Ty*, _Ty>>) { + } else if constexpr (conjunction_v::_Really_trivial>, + _Uses_default_construct<_Alloc, _Ty*, _Ty>>) { + (void) _Al; + if (0 < _Size) { _Copy_memmove(_In, _In + _Size, _Out); - (void) _Al; - } else { - _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Backout._Emplace_back(_In[_Idx]); - } - _Backout._Release(); } + } else { + _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { + _Backout._Emplace_back(_In[_Idx]); + } + _Backout._Release(); } } @@ -1955,17 +1939,17 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const _RERAISE; _CATCH_END } - } else { - if constexpr (_Use_memset_value_construct_v<_Ty*> && _Uses_default_construct<_Alloc, _Ty*>::value) { - (void) _Al; + } else if constexpr (_Use_memset_value_construct_v<_Ty*> && _Uses_default_construct<_Alloc, _Ty*>::value) { + (void) _Al; + if (0 < _Size) { _Zero_range(_Out, _Out + _Size); - } else { - _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { - _Backout._Emplace_back(); - } - _Backout._Release(); } + } else { + _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(); + } + _Backout._Release(); } } @@ -1981,17 +1965,17 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si _RERAISE; _CATCH_END } - } else { - if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { - (void) _Al; + } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { + (void) _Al; + if (0 < _Size) { _CSTD memset(_Out, static_cast(_Val), static_cast(_Size)); - } else { - _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { - _Backout._Emplace_back(_Val); - } - _Backout._Release(); } + } else { + _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + for (size_t _Count = 0; _Count < _Size; ++_Count) { + _Backout._Emplace_back(_Val); + } + _Backout._Release(); } } @@ -2024,7 +2008,7 @@ private: ~_Ref_count_unbounded_array_alloc() = default; // nothing to do; _Storage._Value already destroyed by _Destroy() virtual void _Destroy() noexcept override { // destroy managed resource - if constexpr (!is_trivially_destructible_v>) { + if constexpr (!conjunction_v>, _Uses_default_destroy<_Alloc, _Ty*>>) { _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } @@ -2068,7 +2052,7 @@ private: } virtual void _Destroy() noexcept override { // destroy managed resource - if constexpr (!is_trivially_destructible_v<_Ty>) { + if constexpr (!conjunction_v, _Uses_default_destroy<_Alloc, _Ty*>>) { _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); } From fd8eef9a1044d32d62841750871ec23ca8df44e6 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Wed, 29 Jan 2020 19:12:29 +0100 Subject: [PATCH 21/52] please be happy clang-format --- stl/inc/memory | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index b008f16b6e7..7fda1bb457b 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1295,7 +1295,7 @@ private: requires is_bounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); // clang-format on -#else // ^^^ __cpp_concepts / !__cpp_concepts vvv +#else // ^^^ __cpp_concepts / !__cpp_concepts vvv template friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); @@ -2008,7 +2008,8 @@ private: ~_Ref_count_unbounded_array_alloc() = default; // nothing to do; _Storage._Value already destroyed by _Destroy() virtual void _Destroy() noexcept override { // destroy managed resource - if constexpr (!conjunction_v>, _Uses_default_destroy<_Alloc, _Ty*>>) { + if constexpr (!conjunction_v>, + _Uses_default_destroy<_Alloc, _Ty*>>) { _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } From d5f0687dadf887745ad580caf8ae55f6b7b086c2 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Wed, 29 Jan 2020 19:22:30 +0100 Subject: [PATCH 22/52] oh common clang-format --- stl/inc/memory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/memory b/stl/inc/memory index 7fda1bb457b..83d4c14406f 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1277,7 +1277,7 @@ private: template requires (!is_array_v<_Ty0>) friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); - + template requires is_unbounded_array_v<_Ty0> friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const size_t _Count); From e0d0f08a8c5bffe9cb8e7f2874ae11aa57c5fc32 Mon Sep 17 00:00:00 2001 From: Adam Bucior <35536269+AdamBucior@users.noreply.github.com> Date: Mon, 3 Feb 2020 17:09:05 +0100 Subject: [PATCH 23/52] Formatting --- stl/inc/memory | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 83d4c14406f..9a6777409e8 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1616,7 +1616,7 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ _CATCH_END } } else if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { - if (0 < _Size) { + if (_Size > 0) { _Copy_memmove(_In, _In + _Size, _Out); } } else { @@ -1641,7 +1641,7 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si _CATCH_END } } else if constexpr (_Use_memset_value_construct_v<_Ty*>) { - if (0 < _Size) { + if (_Size > 0) { _Zero_range(_Out, _Out + _Size); } } else { @@ -1666,7 +1666,7 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, _CATCH_END } } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { - if (0 < _Size) { + if (_Size > 0) { _CSTD memset(_Out, static_cast(_Val), _Size); } } else { @@ -1749,8 +1749,8 @@ private: // CLASS TEMPLATE _Ref_count_bounded_array template -class _Ref_count_bounded_array - : public _Ref_count_base { // handle reference counting for bounded array in control block, no allocator +class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in control + // block, no allocator public: _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} @@ -1915,7 +1915,7 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out } else if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ty*, _Ty>>) { (void) _Al; - if (0 < _Size) { + if (_Size > 0) { _Copy_memmove(_In, _In + _Size, _Out); } } else { @@ -1941,7 +1941,7 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const } } else if constexpr (_Use_memset_value_construct_v<_Ty*> && _Uses_default_construct<_Alloc, _Ty*>::value) { (void) _Al; - if (0 < _Size) { + if (_Size > 0) { _Zero_range(_Out, _Out + _Size); } } else { @@ -1967,7 +1967,7 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si } } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { (void) _Al; - if (0 < _Size) { + if (_Size > 0) { _CSTD memset(_Out, static_cast(_Val), static_cast(_Size)); } } else { From 177bfa200f826479330fa67014c9ac66d9d84560 Mon Sep 17 00:00:00 2001 From: Gianni Weinand Date: Tue, 3 Mar 2020 15:00:24 -0800 Subject: [PATCH 24/52] Added tests for make_shared and allocate_shared for arrays. --- .../P0674R1_make_shared_for_arrays/test.cpp | 407 +++++++++++++++++- 1 file changed, 404 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 785bb84adb2..d5aa0906006 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -1,12 +1,222 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include +#include +#include #include #include +#include using namespace std; +int allocationCount = 0; +int canCreate = 10; // Counter to force an exception when constructing a + // sufficiently large ReportAddress array + +struct ReportAddress; +vector ascendingAddressBuffer; +vector descendingAddressBuffer; + +// According to N4849, the default behaviour of new[](size) is to return +// new(size), so only the latter needs to be redefined. +void* operator new(size_t size) { + void* const p = ::operator new(size, nothrow); + + if (p) { + return p; + } else { + throw bad_alloc(); + } +} + +void* operator new(size_t size, const nothrow_t&) noexcept { + void* const result = malloc(size == 0 ? 1 : size); + ++allocationCount; + + return result; +} + +struct InitialValue { + int value = 106; + + InitialValue() {} + + InitialValue(int a, int b) { + value = a + b; + } +}; + +struct ThreeIntWrap { + int v1; + int v2; + int v3; +}; + +struct ReportAddress { + ReportAddress() { + if (canCreate) { + ascendingAddressBuffer.push_back(this); + --canCreate; + } else { + throw runtime_error("Can't create more ReportAddress objects."); + } + } + + ~ReportAddress() { + ++canCreate; + descendingAddressBuffer.push_back(this); + } +}; + +void assert_ascending_init() { + for (unsigned i = 1; i < ascendingAddressBuffer.size(); ++i) + assert(ascendingAddressBuffer[i - 1] < ascendingAddressBuffer[i]); + + ascendingAddressBuffer.clear(); +} + +void assert_descending_destruct() { + for (unsigned i = 1; i < descendingAddressBuffer.size(); ++i) + assert(descendingAddressBuffer[i - 1] > descendingAddressBuffer[i]); + + descendingAddressBuffer.clear(); +} + +template +void assert_shared_use_get(shared_ptr& sp) { + assert(sp.use_count() == 1); + assert(sp.get() != nullptr); +} + +template +shared_ptr make_shared_assert(Args&&... vals) { + int count = allocationCount; + shared_ptr sp = make_shared(forward(vals)...); + assert_shared_use_get(sp); + assert(count + 1 == allocationCount); + return sp; +} + +template != 0, int> = 0> +shared_ptr make_shared_init_assert(const remove_extent_t& val) { + return make_shared_assert(val); +} + +template && extent_v == 0, int> = 0> +shared_ptr make_shared_init_assert(size_t size, const remove_extent_t& val) { + return make_shared_assert(size, val); +} + +template +void test_make_init_destruct_order(Args&&... vals) { + { + try { + shared_ptr sp = make_shared(forward(vals)...); + assert_shared_use_get(sp); + } catch (const runtime_error& exc) { + string err = "Can't create more ReportAddress objects."; + assert(err.compare(exc.what()) == 0); + } + } + assert_ascending_init(); + assert_descending_destruct(); +} + +void test_make_shared_not_array() { + shared_ptr> p0 = make_shared>(); + assert(p0->empty()); + + shared_ptr p1 = make_shared_assert(); + assert(p1->value == 106); + + shared_ptr p2 = make_shared("Meow!", 2, 3); + assert(p2->compare("ow!") == 0); + + shared_ptr p3 = make_shared_assert(40, 2); + assert(p3->value == 42); +} + +void test_make_shared_array_known_bounds() { + shared_ptr p0 = make_shared(); + for (int i = 0; i < 100; ++i) + assert(p0[i].empty()); + + shared_ptr p1 = make_shared_assert(); + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 8; ++j) + for (int k = 0; k < 9; ++k) + assert(p1[i][j][k].value == 106); + + shared_ptr p2 = make_shared({"Meow!", "Purr"}); + for (int i = 0; i < 10; ++i) { + assert(p2[i][0].compare("Meow!") == 0); + assert(p2[i][1].compare("Purr") == 0); + } + + shared_ptr[3]> p3 = make_shared[3]>({9, 9, 9}); + for (int i = 0; i < 3; ++i) + for (int& val : p3[i]) + assert(val == 9); + + shared_ptr p4 = make_shared_init_assert({2, 8, 9}); + for (int i = 0; i < 5; ++i) + assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + + test_make_init_destruct_order(); // success one dimensional + + test_make_init_destruct_order(); // failure one dimensional + + test_make_init_destruct_order(); // success multidimensional + + test_make_init_destruct_order(); // failure multidimensional +} + +void test_make_shared_array_unknown_bounds() { + shared_ptr p0 = make_shared(100); + for (int i = 0; i < 100; ++i) + assert(p0[i].empty()); + + shared_ptr p1 = make_shared_assert(2); + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 8; ++j) + for (int k = 0; k < 9; ++k) + assert(p1[i][j][k].value == 106); + + shared_ptr p2 = make_shared(10, {"Meow!", "Purr"}); + for (int i = 0; i < 10; ++i) { + assert(p2[i][0].compare("Meow!") == 0); + assert(p2[i][1].compare("Purr") == 0); + } + + shared_ptr[]> p3 = make_shared[]>(3, {9, 9, 9}); + for (int i = 0; i < 3; ++i) + for (int& val : p3[i]) + assert(val == 9); + + shared_ptr p4 = make_shared_init_assert(5, {2, 8, 9}); + for (int i = 0; i < 5; ++i) + assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + + shared_ptr p5 = make_shared_assert(0); // p5 cannot be dereferenced + + test_make_init_destruct_order(5); // success one dimensional + + test_make_init_destruct_order(20); // failure one dimensional + + test_make_init_destruct_order(2); // success multidimensional + + test_make_init_destruct_order(3); // failure multidimensional +} + +int constructCount = 0; +int destroyCount = 0; + +inline void assert_construct_destruct_equal() { + assert(constructCount == destroyCount); +} + template struct ConstructConstrainingAllocator { using value_type = T; @@ -30,6 +240,7 @@ struct ConstructConstrainingAllocator { allocator a; static_assert(is_same_v && is_same_v, "incorrect construct call"); allocator_traits>::construct(a, p, forward(vals)...); + constructCount++; } template @@ -37,11 +248,201 @@ struct ConstructConstrainingAllocator { allocator a; static_assert(is_same_v && is_same_v, "incorrect destroy call"); allocator_traits>::destroy(a, p); + destroyCount++; } }; +template +using CustomAlloc = ConstructConstrainingAllocator; + +template +shared_ptr allocate_shared_assert(int elemCount, Args&&... vals) { + int aCount = allocationCount; + int cCount = constructCount; + shared_ptr sp = allocate_shared(forward(vals)...); + assert_shared_use_get(sp); + assert(aCount + 1 == allocationCount); + assert(cCount + elemCount == constructCount); + return sp; +} + +template != 0, int> = 0> +shared_ptr allocate_shared_init_assert(int elemCount, const A& a, const remove_extent_t& val) { + return allocate_shared_assert(elemCount, a, val); +} + +template && extent_v == 0, int> = 0> +shared_ptr allocate_shared_init_assert(int elemCount, const A& a, size_t size, const remove_extent_t& val) { + return allocate_shared_assert(elemCount, a, size, val); +} + +template +void test_allocate_init_destruct_order(Args&&... vals) { + CustomAlloc> a{}; + { + try { + shared_ptr sp = allocate_shared(a, forward(vals)...); + assert_shared_use_get(sp); + } catch (const runtime_error& exc) { + string err = "Can't create more ReportAddress objects."; + assert(err.compare(exc.what()) == 0); + } + } + assert_construct_destruct_equal(); + assert_ascending_init(); + assert_descending_destruct(); +} + +void test_allocate_shared_not_array() { + CustomAlloc> a0{}; + { + shared_ptr> p0 = allocate_shared>(a0); + assert_shared_use_get>(p0); + assert(p0->empty()); + } + assert_construct_destruct_equal(); + + CustomAlloc a1{}; + { + shared_ptr p1 = allocate_shared_assert(1, a1); + assert(p1->value == 106); + } + assert_construct_destruct_equal(); + + CustomAlloc a2{}; + { + shared_ptr p2 = allocate_shared(a2, "Meow!", 2, 3); + assert(p2->compare("ow!") == 0); + } + assert_construct_destruct_equal(); + + { + shared_ptr p3 = allocate_shared_assert(1, a1, 40, 2); + assert(p3->value == 42); + } + assert_construct_destruct_equal(); +} + +void test_allocate_shared_array_known_bounds() { + CustomAlloc a0{}; + { + shared_ptr p0 = allocate_shared(a0); + for (int i = 0; i < 100; ++i) + assert(p0[i].empty()); + } + assert_construct_destruct_equal(); + + CustomAlloc a1{}; + { + shared_ptr p1 = allocate_shared_assert(144, a1); + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 8; ++j) + for (int k = 0; k < 9; ++k) + assert(p1[i][j][k].value == 106); + } + assert_construct_destruct_equal(); + + { + shared_ptr p2 = allocate_shared(a0, {"Meow!", "Purr"}); + for (int i = 0; i < 10; ++i) { + assert(p2[i][0].compare("Meow!") == 0); + assert(p2[i][1].compare("Purr") == 0); + } + } + assert_construct_destruct_equal(); + + + CustomAlloc> a3{}; + { + shared_ptr[3]> p3 = allocate_shared[3]>(a3, {9, 9, 9}); + for (int i = 0; i < 3; ++i) + for (int& val : p3[i]) + assert(val == 9); + } + assert_construct_destruct_equal(); + + CustomAlloc a4{}; + { + shared_ptr p4 = allocate_shared_init_assert(5, a4, {2, 8, 9}); + for (int i = 0; i < 5; ++i) + assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + } + assert_construct_destruct_equal(); + + test_allocate_init_destruct_order(); // success one dimensional + + test_allocate_init_destruct_order(); // failure one dimensional + + test_allocate_init_destruct_order(); // success multidimensional + + test_allocate_init_destruct_order(); // failure multidimensional +} + +void test_allocate_shared_array_unknown_bounds() { + CustomAlloc a0{}; + { + shared_ptr p0 = allocate_shared(a0, 100); + for (int i = 0; i < 100; ++i) + assert(p0[i].empty()); + } + assert_construct_destruct_equal(); + + CustomAlloc a1{}; + { + shared_ptr p1 = allocate_shared_assert(144, a1, 2); + for (int i = 0; i < 2; ++i) + for (int j = 0; j < 8; ++j) + for (int k = 0; k < 9; ++k) + assert(p1[i][j][k].value == 106); + } + assert_construct_destruct_equal(); + + { + shared_ptr p2 = allocate_shared(a0, 10, {"Meow!", "Purr"}); + for (int i = 0; i < 10; ++i) { + assert(p2[i][0].compare("Meow!") == 0); + assert(p2[i][1].compare("Purr") == 0); + } + } + assert_construct_destruct_equal(); + + CustomAlloc> a3{}; + { + shared_ptr[]> p3 = allocate_shared[]>(a3, 3, {9, 9, 9}); + for (int i = 0; i < 3; ++i) + for (int& val : p3[i]) + assert(val == 9); + } + assert_construct_destruct_equal(); + + CustomAlloc a4{}; + { + shared_ptr p4 = allocate_shared_init_assert(5, a4, 5, {2, 8, 9}); + for (int i = 0; i < 5; ++i) + assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + } + assert_construct_destruct_equal(); + + CustomAlloc a5{}; + { shared_ptr p5 = make_shared_assert(0); } // p5 cannot be dereferenced + assert_construct_destruct_equal(); + + test_allocate_init_destruct_order(5); // success one dimensional + + test_allocate_init_destruct_order(20); // failure one dimensional + + test_allocate_init_destruct_order(2); // success multidimensional + + test_allocate_init_destruct_order(3); // failure multidimensional +} + int main() { - ConstructConstrainingAllocator a{}; - (void) allocate_shared(a, 42); - (void) allocate_shared(a, 42); + test_make_shared_not_array(); + test_make_shared_array_known_bounds(); + test_make_shared_array_unknown_bounds(); + + + test_allocate_shared_not_array(); + test_allocate_shared_array_known_bounds(); + test_allocate_shared_array_unknown_bounds(); } From f0098a56ad94b80e7fdfc1b71b77643d521109b6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 3 Mar 2020 18:09:59 -0800 Subject: [PATCH 25/52] GH-482 removed _Max_value. --- stl/inc/memory | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 03a9127d921..7151eecc8ad 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1725,8 +1725,8 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), - _Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), + (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -1758,8 +1758,8 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), - _Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), + (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -2035,7 +2035,7 @@ private: virtual void _Delete_this() noexcept override { // destroy self constexpr size_t _Max_alignment = - _Max_value(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); + (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); using _Storage = aligned_storage_t<_Max_alignment, _Max_alignment>; _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); this->~_Ref_count_unbounded_array_alloc(); @@ -2107,7 +2107,7 @@ _NODISCARD shared_ptr<_Ty> make_shared( const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = - aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); @@ -2128,7 +2128,7 @@ _NODISCARD shared_ptr<_Ty> make_shared( const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = - aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); @@ -2195,7 +2195,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = - aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); @@ -2217,7 +2217,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const size_t _Coun const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = - aligned_storage_t<_Max_value(alignof(_Ty), alignof(_Refc)), _Max_value(alignof(_Ty), alignof(_Refc))>; + aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); From 6722355797aac1d910add88b7ec5922731313f8e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 00:19:15 -0800 Subject: [PATCH 26/52] Adjust and test feature-test macros. Make __cpp_lib_shared_ptr_arrays vary with _HAS_CXX20 instead of __cpp_concepts (as the feature isn't inherently dependent on concepts). Now that more feature-test macros have varying values, extract them to separate preprocessor blocks where the logic is easier to read. --- stl/inc/yvals_core.h | 32 ++++++++++--------- .../VSO_0157762_feature_test_macros/test.cpp | 27 +++++++++++----- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/stl/inc/yvals_core.h b/stl/inc/yvals_core.h index 3d099d18328..b08deb088a4 100644 --- a/stl/inc/yvals_core.h +++ b/stl/inc/yvals_core.h @@ -1001,18 +1001,11 @@ #define __cpp_lib_map_try_emplace 201411L #define __cpp_lib_nonmember_container_access 201411L #define __cpp_lib_shared_mutex 201505L - -#ifdef __cpp_concepts -#define __cpp_lib_shared_ptr_arrays 201707L -#else // __cpp_concepts -#define __cpp_lib_shared_ptr_arrays 201611L -#endif // __cpp_concepts - -#define __cpp_lib_transparent_operators 201510L -#define __cpp_lib_type_trait_variable_templates 201510L -#define __cpp_lib_uncaught_exceptions 201411L -#define __cpp_lib_unordered_map_try_emplace 201411L -#define __cpp_lib_void_t 201411L +#define __cpp_lib_transparent_operators 201510L +#define __cpp_lib_type_trait_variable_templates 201510L +#define __cpp_lib_uncaught_exceptions 201411L +#define __cpp_lib_unordered_map_try_emplace 201411L +#define __cpp_lib_void_t 201411L #if _HAS_CXX17 #define __cpp_lib_any 201606L @@ -1023,8 +1016,7 @@ #if _HAS_STD_BYTE #define __cpp_lib_byte 201603L #endif // _HAS_STD_BYTE -#define __cpp_lib_chrono 201611L -#define __cpp_lib_clamp 201603L +#define __cpp_lib_clamp 201603L #ifndef _M_CEE #define __cpp_lib_execution 201603L #endif // _M_CEE @@ -1053,8 +1045,12 @@ #define __cpp_lib_string_view 201803L #define __cpp_lib_to_chars 201611L #define __cpp_lib_variant 201606L +#endif // _HAS_CXX17 + +#if _HAS_CXX17 +#define __cpp_lib_chrono 201611L // P0505R0 constexpr For (Again) #else // _HAS_CXX17 -#define __cpp_lib_chrono 201510L +#define __cpp_lib_chrono 201510L // P0092R1 floor(), ceil(), round(), abs() #endif // _HAS_CXX17 // C++20 @@ -1108,6 +1104,12 @@ #define __cpp_lib_unwrap_ref 201811L #endif // _HAS_CXX20 +#if _HAS_CXX20 +#define __cpp_lib_shared_ptr_arrays 201707L // P0674R1 make_shared() For Arrays +#else // _HAS_CXX20 +#define __cpp_lib_shared_ptr_arrays 201611L // P0497R0 Fixing shared_ptr For Arrays +#endif // _HAS_CXX20 + // EXPERIMENTAL #define __cpp_lib_experimental_erase_if 201411L #define __cpp_lib_experimental_filesystem 201406L diff --git a/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp b/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp index 6c17c18ad45..d8cdb3e9f7f 100644 --- a/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp +++ b/tests/std/tests/VSO_0157762_feature_test_macros/test.cpp @@ -722,6 +722,25 @@ STATIC_ASSERT(__cpp_lib_chrono == 201510L); #endif +// Always defined to varying values (C++14 versus C++20-and-newer mode). + +#ifndef __cpp_lib_shared_ptr_arrays +#error BOOM +#elif CXX20_MODE +#if __cpp_lib_shared_ptr_arrays != 201707L +#error BOOM +#else +STATIC_ASSERT(__cpp_lib_shared_ptr_arrays == 201707L); +#endif +#else +#if __cpp_lib_shared_ptr_arrays != 201611L +#error BOOM +#else +STATIC_ASSERT(__cpp_lib_shared_ptr_arrays == 201611L); +#endif +#endif + + // Always defined to specific values. #ifndef __cpp_lib_addressof_constexpr @@ -948,14 +967,6 @@ STATIC_ASSERT(__cpp_lib_robust_nonmodifying_seq_ops == 201304L); STATIC_ASSERT(__cpp_lib_shared_mutex == 201505L); #endif -#ifndef __cpp_lib_shared_ptr_arrays -#error BOOM -#elif __cpp_lib_shared_ptr_arrays != 201611L -#error BOOM -#else -STATIC_ASSERT(__cpp_lib_shared_ptr_arrays == 201611L); -#endif - #ifdef _M_CEE #ifdef __cpp_lib_shared_timed_mutex #error BOOM From dcf7dbdd6931ad91288d925aec48282ea43e6dfb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 00:29:07 -0800 Subject: [PATCH 27/52] memory already includes xmemory, which includes xutility, which includes utility. Ironically, the STL's product code doesn't follow a coherent philosophy around "include what you use". --- stl/inc/memory | 1 - 1 file changed, 1 deletion(-) diff --git a/stl/inc/memory b/stl/inc/memory index 7151eecc8ad..7002c11e08a 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -12,7 +12,6 @@ #include #include #include -#include #include #pragma pack(push, _CRT_PACKING) From 7ae0911520eede2532b48ee9b6b9a7f0793db492 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 01:19:13 -0800 Subject: [PATCH 28/52] Fix test typo affecting coverage. This was copy-pasted from make_shared, but it meant to test allocate_shared. Clang noticed that `a5` was unused. --- tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index d5aa0906006..c25ce0ffd09 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -424,7 +424,7 @@ void test_allocate_shared_array_unknown_bounds() { assert_construct_destruct_equal(); CustomAlloc a5{}; - { shared_ptr p5 = make_shared_assert(0); } // p5 cannot be dereferenced + { shared_ptr p5 = allocate_shared_assert(0, a5, 0); } // p5 cannot be dereferenced assert_construct_destruct_equal(); test_allocate_init_destruct_order(5); // success one dimensional From 272afd658ccf9091f55208a71f6e2624275b13b5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 00:50:27 -0800 Subject: [PATCH 29/52] Replace concepts usage with SFINAE. This is less elegant, but works for Clang 9 and EDG. --- stl/inc/memory | 113 ++++++++++++++++++++----------------------------- 1 file changed, 47 insertions(+), 66 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 7002c11e08a..227ddb363b2 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1269,56 +1269,47 @@ private: _Owner._Call_deleter = false; } -#ifdef __cpp_concepts - // clang-format off +#if _HAS_CXX20 template - requires (!is_array_v<_Ty0>) - friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); + friend enable_if_t, shared_ptr<_Ty0>> make_shared(_Types&&... _Args); template - requires is_unbounded_array_v<_Ty0> - friend shared_ptr<_Ty0> make_shared(const size_t _Count); + friend enable_if_t, shared_ptr<_Ty0>> make_shared(const size_t _Count); template - requires is_unbounded_array_v<_Ty0> - friend shared_ptr<_Ty0> make_shared(const size_t _Count, const remove_extent_t<_Ty0>& _Val); + friend enable_if_t, shared_ptr<_Ty0>> make_shared( + const size_t _Count, const remove_extent_t<_Ty0>& _Val); template - requires is_bounded_array_v<_Ty0> - friend shared_ptr<_Ty0> make_shared(); + friend enable_if_t, shared_ptr<_Ty0>> make_shared(); template - requires is_bounded_array_v<_Ty0> - friend shared_ptr<_Ty0> make_shared(const remove_extent_t<_Ty0>& _Val); + friend enable_if_t, shared_ptr<_Ty0>> make_shared(const remove_extent_t<_Ty0>& _Val); template - requires (!is_array_v<_Ty0>) - friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); template - requires is_unbounded_array_v<_Ty0> - friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const size_t _Count); + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( + const _Alloc& _Al_arg, const size_t _Count); template - requires is_unbounded_array_v<_Ty0> - friend shared_ptr<_Ty0> allocate_shared( + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( const _Alloc& _Al_arg, const size_t _Count, const remove_extent_t<_Ty0>& _Val); template - requires is_bounded_array_v<_Ty0> - friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg); + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg); template - requires is_bounded_array_v<_Ty0> - friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); - // clang-format on -#else // ^^^ __cpp_concepts / !__cpp_concepts vvv + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( + const _Alloc& _Al_arg, const remove_extent_t<_Ty0>& _Val); +#else // ^^^ _HAS_CXX20 / !_HAS_CXX20 vvv template friend shared_ptr<_Ty0> make_shared(_Types&&... _Args); template friend shared_ptr<_Ty0> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); -#endif // !__cpp_concepts +#endif // !_HAS_CXX20 template void _Set_ptr_rep_and_enable_shared(_Ux* const _Px, _Ref_count_base* const _Rx) noexcept { // take ownership of _Px @@ -1567,7 +1558,7 @@ private: } }; -#ifdef __cpp_concepts +#if _HAS_CXX20 template constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { using _Signed = make_signed_t<_Ty>; @@ -1792,7 +1783,7 @@ private: delete this; } }; -#endif // __cpp_concepts +#endif // _HAS_CXX20 // CLASS TEMPLATE _Ebco_base template class _Uninitialized_rev_destroying_backout_al { // struct to undo partially constructed ranges in // _Uninitialized_xxx_al algorithms @@ -2082,27 +2073,26 @@ private: _Deallocate_plain(_Al, this); } }; -#endif // __cpp_concepts +#endif // _HAS_CXX20 // FUNCTION TEMPLATE make_shared -// clang-format off template -#ifdef __cpp_concepts - requires (!is_array_v<_Ty>) -#endif // __cpp_concepts -_NODISCARD shared_ptr<_Ty> make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object +_NODISCARD +#if _HAS_CXX20 + enable_if_t, shared_ptr<_Ty>> +#else // _HAS_CXX20 + shared_ptr<_Ty> +#endif // _HAS_CXX20 + make_shared(_Types&&... _Args) { // make a shared_ptr to non-array object const auto _Rx = new _Ref_count_obj2<_Ty>(_STD forward<_Types>(_Args)...); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_STD addressof(_Rx->_Storage._Value), _Rx); return _Ret; } -// clang-format on -#ifdef __cpp_concepts -// clang-format off +#if _HAS_CXX20 template - requires is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared( +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = @@ -2122,8 +2112,7 @@ _NODISCARD shared_ptr<_Ty> make_shared( } template - requires is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared( +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = @@ -2143,8 +2132,7 @@ _NODISCARD shared_ptr<_Ty> make_shared( } template - requires is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded array +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); @@ -2152,25 +2140,24 @@ _NODISCARD shared_ptr<_Ty> make_shared() { // make a shared_ptr to a bounded arr } template - requires is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> make_shared( +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); return _Ret; } -// clang-format on -#endif // __cpp_concepts +#endif // _HAS_CXX20 // FUNCTION TEMPLATE allocate_shared -// clang-format off template -#ifdef __cpp_concepts - requires (!is_array_v<_Ty>) -#endif // __cpp_concepts -_NODISCARD shared_ptr<_Ty> allocate_shared( - const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object +_NODISCARD +#if _HAS_CXX20 + enable_if_t, shared_ptr<_Ty>> +#else // _HAS_CXX20 + shared_ptr<_Ty> +#endif // _HAS_CXX20 + allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether // allocator::construct sees T or const T when _Ty is const qualified) using _Refoa = _Ref_count_obj_alloc2, _Alloc>; @@ -2184,13 +2171,10 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); return _Ret; } -// clang-format on -#ifdef __cpp_concepts -// clang-format off +#if _HAS_CXX20 template - requires is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared( +_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = @@ -2211,8 +2195,8 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( } template - requires is_unbounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const size_t _Count, +_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared(const _Alloc& _Al, + const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = @@ -2233,8 +2217,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared(const _Alloc& _Al, const size_t _Coun } template - requires is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared( +_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -2249,8 +2232,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( } template - requires is_bounded_array_v<_Ty> -_NODISCARD shared_ptr<_Ty> allocate_shared( +_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; @@ -2263,8 +2245,7 @@ _NODISCARD shared_ptr<_Ty> allocate_shared( _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); return _Ret; } -// clang-format on -#endif // __cpp_concepts +#endif // _HAS_CXX20 // CLASS TEMPLATE weak_ptr template From bdc84c518e6c24e92dea548421d92198c2d59b7d Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 13:14:28 -0800 Subject: [PATCH 30/52] Use usual_latest_matrix.lst to test this C++20 feature. --- tests/std/tests/P0674R1_make_shared_for_arrays/env.lst | 2 +- tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/env.lst b/tests/std/tests/P0674R1_make_shared_for_arrays/env.lst index 19f025bd0e6..642f530ffad 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/env.lst +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_matrix.lst +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index c25ce0ffd09..6ee8656cfbb 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -441,7 +441,6 @@ int main() { test_make_shared_array_known_bounds(); test_make_shared_array_unknown_bounds(); - test_allocate_shared_not_array(); test_allocate_shared_array_known_bounds(); test_allocate_shared_array_unknown_bounds(); From 17f2ef65bc2986428a01a69c826cd0d4453f978e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 14:21:14 -0800 Subject: [PATCH 31/52] Fix sign-conversion warnings in the test. When constants like `2` are directly passed to functions taking `size_t`, the compiler can see that the value is being preserved, so it doesn't warn. However, when `2` is perfectly forwarded, only the type `int` is forwarded - the constant nature isn't part of the type system. So, the compiler will warn if it sees a forwarded `int` converted to `size_t`. The fix is to use `2u` etc. in the source code. `unsigned int` being converted to `size_t` is known to be value-preserving (for 64-bit `size_t`, it's a widening). --- .../P0674R1_make_shared_for_arrays/test.cpp | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 6ee8656cfbb..766f5503b22 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -131,7 +131,7 @@ void test_make_shared_not_array() { shared_ptr p1 = make_shared_assert(); assert(p1->value == 106); - shared_ptr p2 = make_shared("Meow!", 2, 3); + shared_ptr p2 = make_shared("Meow!", 2u, 3u); assert(p2->compare("ow!") == 0); shared_ptr p3 = make_shared_assert(40, 2); @@ -178,7 +178,7 @@ void test_make_shared_array_unknown_bounds() { for (int i = 0; i < 100; ++i) assert(p0[i].empty()); - shared_ptr p1 = make_shared_assert(2); + shared_ptr p1 = make_shared_assert(2u); for (int i = 0; i < 2; ++i) for (int j = 0; j < 8; ++j) for (int k = 0; k < 9; ++k) @@ -199,15 +199,15 @@ void test_make_shared_array_unknown_bounds() { for (int i = 0; i < 5; ++i) assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); - shared_ptr p5 = make_shared_assert(0); // p5 cannot be dereferenced + shared_ptr p5 = make_shared_assert(0u); // p5 cannot be dereferenced - test_make_init_destruct_order(5); // success one dimensional + test_make_init_destruct_order(5u); // success one dimensional - test_make_init_destruct_order(20); // failure one dimensional + test_make_init_destruct_order(20u); // failure one dimensional - test_make_init_destruct_order(2); // success multidimensional + test_make_init_destruct_order(2u); // success multidimensional - test_make_init_destruct_order(3); // failure multidimensional + test_make_init_destruct_order(3u); // failure multidimensional } int constructCount = 0; @@ -311,7 +311,7 @@ void test_allocate_shared_not_array() { CustomAlloc a2{}; { - shared_ptr p2 = allocate_shared(a2, "Meow!", 2, 3); + shared_ptr p2 = allocate_shared(a2, "Meow!", 2u, 3u); assert(p2->compare("ow!") == 0); } assert_construct_destruct_equal(); @@ -389,7 +389,7 @@ void test_allocate_shared_array_unknown_bounds() { CustomAlloc a1{}; { - shared_ptr p1 = allocate_shared_assert(144, a1, 2); + shared_ptr p1 = allocate_shared_assert(144, a1, 2u); for (int i = 0; i < 2; ++i) for (int j = 0; j < 8; ++j) for (int k = 0; k < 9; ++k) @@ -424,16 +424,16 @@ void test_allocate_shared_array_unknown_bounds() { assert_construct_destruct_equal(); CustomAlloc a5{}; - { shared_ptr p5 = allocate_shared_assert(0, a5, 0); } // p5 cannot be dereferenced + { shared_ptr p5 = allocate_shared_assert(0, a5, 0u); } // p5 cannot be dereferenced assert_construct_destruct_equal(); - test_allocate_init_destruct_order(5); // success one dimensional + test_allocate_init_destruct_order(5u); // success one dimensional - test_allocate_init_destruct_order(20); // failure one dimensional + test_allocate_init_destruct_order(20u); // failure one dimensional - test_allocate_init_destruct_order(2); // success multidimensional + test_allocate_init_destruct_order(2u); // success multidimensional - test_allocate_init_destruct_order(3); // failure multidimensional + test_allocate_init_destruct_order(3u); // failure multidimensional } int main() { From 11834ffda470b34d2f209f0aaf8bd3dd1162e0a0 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 14:34:58 -0800 Subject: [PATCH 32/52] Silence SAL annotation warning C28251 in the test. This is necessary whenever we replace `new` in test code. --- tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 766f5503b22..9651eb757e6 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -11,6 +11,8 @@ using namespace std; +#pragma warning(disable : 28251) // Inconsistent annotation for 'new': this instance has no annotations. + int allocationCount = 0; int canCreate = 10; // Counter to force an exception when constructing a // sufficiently large ReportAddress array From c80db826c02733219adf73b9ea8feb5751384c94 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 14:21:26 -0800 Subject: [PATCH 33/52] Fix sign-conversion warning, use C++ casts. First, this was using functional-style C-semantics casts to convert from unsigned to signed. We conventionally avoid all C-semantics casts regardless of style (except `(void)`). Second, this was implicitly converting from signed back to unsigned, emitting warnings for which we attempt to be clean (even though they're off-by-default). Finally, this had unnecessary parentheses in the conditional operator; it's a judgement call, but stylistically we tend to avoid parentheses given these operators. --- stl/inc/memory | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 227ddb363b2..948f1055e15 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1562,8 +1562,8 @@ private: template constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { using _Signed = make_signed_t<_Ty>; - const auto _Res = _STD div(_Signed(_Val1), _Signed(_Val2)); - return (_Res.rem == 0) ? (_Res.quot) : (_Res.quot + 1); + const auto _Res = _STD div(static_cast<_Signed>(_Val1), static_cast<_Signed>(_Val2)); + return static_cast<_Ty>(_Res.rem == 0 ? _Res.quot : _Res.quot + 1); } template From f762deeb47a76594358203dd6e7060821a79f4d3 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 5 Mar 2020 15:05:12 -0800 Subject: [PATCH 34/52] FIXME: Silence buffer overrun warning C6386. This must be properly investigated before merging. --- stl/inc/memory | 3 +++ 1 file changed, 3 insertions(+) diff --git a/stl/inc/memory b/stl/inc/memory index 948f1055e15..7ecdb044c96 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -2091,6 +2091,8 @@ _NODISCARD } #if _HAS_CXX20 +#pragma warning(push) // ***FIXME*** MUST INVESTIGATE BEFORE MERGING ***FIXME*** +#pragma warning(disable : 6386) // Buffer overrun while writing to '_Rx' template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( const size_t _Count) { // make a shared_ptr to an unbounded array @@ -2130,6 +2132,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } +#pragma warning(pop) // ***FIXME*** MUST INVESTIGATE BEFORE MERGING ***FIXME*** template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { // make a shared_ptr to a bounded array From 07b7b161d697dff71b6affa348afadca23316c59 Mon Sep 17 00:00:00 2001 From: Adam Date: Fri, 6 Mar 2020 14:41:18 +0100 Subject: [PATCH 35/52] _Div_ceil is no longer constexpr --- stl/inc/memory | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/memory b/stl/inc/memory index 7ecdb044c96..45976ea2256 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1560,7 +1560,7 @@ private: #if _HAS_CXX20 template -constexpr _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { +_Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { using _Signed = make_signed_t<_Ty>; const auto _Res = _STD div(static_cast<_Signed>(_Val1), static_cast<_Signed>(_Val2)); return static_cast<_Ty>(_Res.rem == 0 ? _Res.quot : _Res.quot + 1); From dbe217ab3d4dae60b547c943ab3592e27f6704d6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 10 Mar 2020 22:29:59 -0700 Subject: [PATCH 36/52] In friend declarations, don't mark value parameters as const. --- stl/inc/memory | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 45976ea2256..972765aa50d 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1274,11 +1274,11 @@ private: friend enable_if_t, shared_ptr<_Ty0>> make_shared(_Types&&... _Args); template - friend enable_if_t, shared_ptr<_Ty0>> make_shared(const size_t _Count); + friend enable_if_t, shared_ptr<_Ty0>> make_shared(size_t _Count); template friend enable_if_t, shared_ptr<_Ty0>> make_shared( - const size_t _Count, const remove_extent_t<_Ty0>& _Val); + size_t _Count, const remove_extent_t<_Ty0>& _Val); template friend enable_if_t, shared_ptr<_Ty0>> make_shared(); @@ -1291,11 +1291,11 @@ private: template friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( - const _Alloc& _Al_arg, const size_t _Count); + const _Alloc& _Al_arg, size_t _Count); template friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( - const _Alloc& _Al_arg, const size_t _Count, const remove_extent_t<_Ty0>& _Val); + const _Alloc& _Al_arg, size_t _Count, const remove_extent_t<_Ty0>& _Val); template friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg); From 22b02629d1cbba3771a6a9b56f90f910ae3db319 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 10 Mar 2020 22:58:22 -0700 Subject: [PATCH 37/52] Adjust comments and class/struct. In new code, we generally prefer to "detach" introductory comments from braces, especially when that reduces wrapping for the comment and the function parameters. Conversely, we generally prefer to attach TRANSITION comments to the affected lines, so we can easily see what needs to be adjusted when the mentioned bug is fixed. `_Uninitialized_rev_destroying_backout_al` is a class that uses private access control. Therefore, its comment should refer to it as a class. Additionally, we generally avoid relying on classes defaulting to private access control; this is one of the relatively few places where we prefer to repeat the default. --- stl/inc/memory | 77 ++++++++++++++++++++++++-------------------------- 1 file changed, 37 insertions(+), 40 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 972765aa50d..ff3300c6147 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1567,8 +1567,8 @@ _Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { } template -struct _Uninitialized_rev_destroying_backout { // struct to undo partially constructed ranges in _Uninitialized_xxx - // algorithms +struct _Uninitialized_rev_destroying_backout { + // struct to undo partially constructed ranges in _Uninitialized_xxx algorithms _NoThrowIt _First; _NoThrowIt _Last; @@ -1602,8 +1602,7 @@ template void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) { while (_Size > 0) { --_Size; - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 _Reverse_destroy_multidimensional_n(_Arr[_Size], extent_v<_Ty>); } else { _Destroy_in_place(_Arr[_Size]); @@ -1613,8 +1612,7 @@ void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) { template void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional(_In[_Idx], _Out[_Idx]); @@ -1638,8 +1636,7 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ template void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_value_construct_multidimensional_n(_Out[_Idx], extent_v<_Ty>); @@ -1663,8 +1660,7 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si template void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, const _Ty& _Val) { - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); @@ -1688,8 +1684,8 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, // CLASS TEMPLATE _Ref_count_unbounded_array template >> -class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array with - // non-trivial destruction in control block, no allocator +class _Ref_count_unbounded_array : public _Ref_count_base { + // handle reference counting for unbounded array with non-trivial destruction in control block, no allocator public: explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); @@ -1723,9 +1719,8 @@ private: }; template -class _Ref_count_unbounded_array<_Ty, true> : public _Ref_count_base { // handle reference counting for unbounded array - // with trivial destruction in control block, - // no allocator +class _Ref_count_unbounded_array<_Ty, true> : public _Ref_count_base { + // handle reference counting for unbounded array with trivial destruction in control block, no allocator public: explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Count); @@ -1757,8 +1752,8 @@ private: // CLASS TEMPLATE _Ref_count_bounded_array template -class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in control - // block, no allocator +class _Ref_count_bounded_array : public _Ref_count_base { + // handle reference counting for bounded array in control block, no allocator public: _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} @@ -1861,8 +1856,10 @@ private: #if _HAS_CXX20 template -class _Uninitialized_rev_destroying_backout_al { // struct to undo partially constructed ranges in - // _Uninitialized_xxx_al algorithms +class _Uninitialized_rev_destroying_backout_al { + // class to undo partially constructed ranges in _Uninitialized_xxx_al algorithms + +private: using pointer = _Alloc_ptr_t<_Alloc>; public: @@ -1899,8 +1896,7 @@ template void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Alloc& _Al) { while (_Size > 0) { --_Size; - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 _Reverse_destroy_multidimensional_n_al(_Arr[_Size], extent_v<_Ty>, _Al); } else { allocator_traits<_Alloc>::destroy(_Al, _Arr + _Size); @@ -1910,8 +1906,7 @@ void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Allo template void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], _Alloc& _Al) { - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); @@ -1937,8 +1932,7 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out template void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const size_t _Size, _Alloc& _Al) { - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); @@ -1963,8 +1957,7 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const template void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Size, const _Ty& _Val, _Alloc& _Al) { - // TRANSITION, LLVM-42404 - if constexpr ((rank_v<_Ty>) > 0) { + if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _TRY_BEGIN _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); @@ -2094,8 +2087,8 @@ _NODISCARD #pragma warning(push) // ***FIXME*** MUST INVESTIGATE BEFORE MERGING ***FIXME*** #pragma warning(disable : 6386) // Buffer overrun while writing to '_Rx' template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( - const size_t _Count) { // make a shared_ptr to an unbounded array +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { + // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; @@ -2115,7 +2108,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( - const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array + const size_t _Count, const remove_extent_t<_Ty>& _Val) { + // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; @@ -2135,7 +2129,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( #pragma warning(pop) // ***FIXME*** MUST INVESTIGATE BEFORE MERGING ***FIXME*** template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { // make a shared_ptr to a bounded array +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { + // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); @@ -2143,8 +2138,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( - const _STD remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const _STD remove_extent_t<_Ty>& _Val) { + // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Storage._Value, _Rx); @@ -2178,7 +2173,8 @@ _NODISCARD #if _HAS_CXX20 template _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( - const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array + const _Alloc& _Al, const size_t _Count) { + // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; @@ -2198,9 +2194,9 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shar } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared(const _Alloc& _Al, - const size_t _Count, - const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array +_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( + const _Alloc& _Al, const size_t _Count, const remove_extent_t<_Ty>& _Val) { + // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; @@ -2220,8 +2216,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shar } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( - const _Alloc& _Al) { // make a shared_ptr to a bounded array +_NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared(const _Alloc& _Al) { + // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); @@ -2236,7 +2232,8 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared template _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( - const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array + const _Alloc& _Al, const remove_extent_t<_Ty>& _Val) { + // make a shared_ptr to a bounded array using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); From 00454a2ac433a8b9db857b45cfd7c0e1c5756106 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 10 Mar 2020 23:11:04 -0700 Subject: [PATCH 38/52] Flip the specialization of `_Ref_count_unbounded_array`. This is a stylistic nitpick - when we have a primary template and a specialization, it's slightly more readable for the primary template to be the `true` case. That's because it's the one that mentions `is_trivially_destructible_v` here. (This diff looks messy, but it's purely moving code around.) --- stl/inc/memory | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index ff3300c6147..e1f08a6a474 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1685,18 +1685,17 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, // CLASS TEMPLATE _Ref_count_unbounded_array template >> class _Ref_count_unbounded_array : public _Ref_count_base { - // handle reference counting for unbounded array with non-trivial destruction in control block, no allocator + // handle reference counting for unbounded array with trivial destruction in control block, no allocator public: - explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { - _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); + explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { + _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Count); } - explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) - : _Ref_count_base(), _Size(_Count) { - _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Size, _Val); + explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) : _Ref_count_base() { + _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Count, _Val); } - ~_Ref_count_unbounded_array() = default; // nothing to do, _Storage was already destroyed in _Destroy + ~_Ref_count_unbounded_array() = default; // nothing to do, _Ty is trivially destructible auto _Get_ptr() { return reinterpret_cast*>( @@ -1704,10 +1703,8 @@ public: } private: - size_t _Size; - virtual void _Destroy() noexcept override { // destroy managed resource - _Reverse_destroy_multidimensional_n(_Get_ptr(), _Size); + // nothing to do, _Ty is trivially destructible } virtual void _Delete_this() noexcept override { // destroy self @@ -1719,18 +1716,19 @@ private: }; template -class _Ref_count_unbounded_array<_Ty, true> : public _Ref_count_base { - // handle reference counting for unbounded array with trivial destruction in control block, no allocator +class _Ref_count_unbounded_array<_Ty, false> : public _Ref_count_base { + // handle reference counting for unbounded array with non-trivial destruction in control block, no allocator public: - explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { - _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Count); + explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { + _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); } - explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) : _Ref_count_base() { - _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Count, _Val); + explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) + : _Ref_count_base(), _Size(_Count) { + _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Size, _Val); } - ~_Ref_count_unbounded_array() = default; // nothing to do, _Ty is trivially destructible + ~_Ref_count_unbounded_array() = default; // nothing to do, _Storage was already destroyed in _Destroy auto _Get_ptr() { return reinterpret_cast*>( @@ -1738,8 +1736,10 @@ public: } private: + size_t _Size; + virtual void _Destroy() noexcept override { // destroy managed resource - // nothing to do, _Ty is trivially destructible + _Reverse_destroy_multidimensional_n(_Get_ptr(), _Size); } virtual void _Delete_this() noexcept override { // destroy self @@ -2138,7 +2138,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { } template -_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const _STD remove_extent_t<_Ty>& _Val) { +_NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to a bounded array const auto _Rx = new _Ref_count_bounded_array<_Ty>(_Val); shared_ptr<_Ty> _Ret; From 68ad0e4a5b64220d1fd523181c02147c0d4ab71e Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 12 Mar 2020 00:49:18 -0700 Subject: [PATCH 39/52] Address some code review comments. Simplify `_Div_ceil`; still need to handle overflow here and elsewhere. Use RAII guards for reverse destruction. (Also use CTAD.) Drop unnecessary `if (_Size > 0)` branching. Comment `_Destroy_in_place(_Storage)` as being intentional. Drop unnecessary `static_cast`. --- stl/inc/memory | 124 ++++++++++++++++++++++++++++--------------------- 1 file changed, 71 insertions(+), 53 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index e1f08a6a474..f5a83341473 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1560,10 +1560,8 @@ private: #if _HAS_CXX20 template -_Ty _Div_ceil(_Ty _Val1, _Ty _Val2) noexcept { - using _Signed = make_signed_t<_Ty>; - const auto _Res = _STD div(static_cast<_Signed>(_Val1), static_cast<_Signed>(_Val2)); - return static_cast<_Ty>(_Res.rem == 0 ? _Res.quot : _Res.quot + 1); +_NODISCARD constexpr _Ty _Div_ceil(const _Ty _Val1, const _Ty _Val2) noexcept { + return (_Val1 + _Val2 - 1) / _Val2; // ***FIXME*** OVERFLOW } template @@ -1610,21 +1608,40 @@ void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) { } } +template +class _Reverse_destroy_multidimensional_n_guard { +public: + _Reverse_destroy_multidimensional_n_guard(_Ty* const _Arr_, const size_t _Size_) noexcept + : _Arr(_Arr_), _Size(_Size_) {} + + void _Dismiss() noexcept { + _Arr = nullptr; + } + + ~_Reverse_destroy_multidimensional_n_guard() { + if (_Arr) { + _Reverse_destroy_multidimensional_n(_Arr, _Size); + } + } + + _Reverse_destroy_multidimensional_n_guard(const _Reverse_destroy_multidimensional_n_guard&) = delete; + _Reverse_destroy_multidimensional_n_guard& operator=(const _Reverse_destroy_multidimensional_n_guard&) = delete; + +private: + _Ty* _Arr; + size_t _Size; +}; + template void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _TRY_BEGIN + _Reverse_destroy_multidimensional_n_guard _Guard{_Out, _Idx}; _Uninitialized_copy_multidimensional(_In[_Idx], _Out[_Idx]); - _CATCH_ALL - _Reverse_destroy_multidimensional_n(_Out, _Idx); - _RERAISE; - _CATCH_END + _Guard._Dismiss(); } } else if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { - if (_Size > 0) { - _Copy_memmove(_In, _In + _Size, _Out); - } + _Copy_memmove(_In, _In + _Size, _Out); } else { _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1638,17 +1655,12 @@ template void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _TRY_BEGIN + _Reverse_destroy_multidimensional_n_guard _Guard{_Out, _Idx}; _Uninitialized_value_construct_multidimensional_n(_Out[_Idx], extent_v<_Ty>); - _CATCH_ALL - _Reverse_destroy_multidimensional_n(_Out, _Idx); - _RERAISE; - _CATCH_END + _Guard._Dismiss(); } } else if constexpr (_Use_memset_value_construct_v<_Ty*>) { - if (_Size > 0) { - _Zero_range(_Out, _Out + _Size); - } + _Zero_range(_Out, _Out + _Size); } else { _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; for (size_t _Count = 0; _Count < _Size; ++_Count) { @@ -1662,17 +1674,12 @@ template void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, const _Ty& _Val) { if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _TRY_BEGIN + _Reverse_destroy_multidimensional_n_guard _Guard{_Out, _Idx}; _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); - _CATCH_ALL - _Reverse_destroy_multidimensional_n(_Out, _Idx); - _RERAISE; - _CATCH_END + _Guard._Dismiss(); } } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { - if (_Size > 0) { - _CSTD memset(_Out, static_cast(_Val), _Size); - } + _CSTD memset(_Out, static_cast(_Val), _Size); } else { _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; for (size_t _Count = 0; _Count < _Size; ++_Count) { @@ -1771,7 +1778,7 @@ public: private: virtual void _Destroy() noexcept override { // destroy managed resource - _Destroy_in_place(_Storage); + _Destroy_in_place(_Storage); // not _Storage._Value, see N4849 [expr.prim.id.dtor] } virtual void _Delete_this() noexcept override { // destroy self @@ -1904,23 +1911,44 @@ void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Allo } } +template +class _Reverse_destroy_multidimensional_n_al_guard { +public: + _Reverse_destroy_multidimensional_n_al_guard(_Ty* const _Arr_, const size_t _Size_, _Alloc& _Al_) noexcept + : _Arr(_Arr_), _Size(_Size_), _Al(_Al_) {} + + void _Dismiss() noexcept { + _Arr = nullptr; + } + + ~_Reverse_destroy_multidimensional_n_al_guard() { + if (_Arr) { + _Reverse_destroy_multidimensional_n_al(_Arr, _Size, _Al); + } + } + + _Reverse_destroy_multidimensional_n_al_guard(const _Reverse_destroy_multidimensional_n_al_guard&) = delete; + _Reverse_destroy_multidimensional_n_al_guard& operator=( // + const _Reverse_destroy_multidimensional_n_al_guard&) = delete; + +private: + _Ty* _Arr; + size_t _Size; + _Alloc& _Al; +}; + template void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], _Alloc& _Al) { if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _TRY_BEGIN + _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); - _CATCH_ALL - _Reverse_destroy_multidimensional_n_al(_Out, _Idx, _Al); - _RERAISE; - _CATCH_END + _Guard._Dismiss(); } } else if constexpr (conjunction_v::_Really_trivial>, _Uses_default_construct<_Alloc, _Ty*, _Ty>>) { (void) _Al; - if (_Size > 0) { - _Copy_memmove(_In, _In + _Size, _Out); - } + _Copy_memmove(_In, _In + _Size, _Out); } else { _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1934,18 +1962,13 @@ template void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const size_t _Size, _Alloc& _Al) { if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _TRY_BEGIN + _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); - _CATCH_ALL - _Reverse_destroy_multidimensional_n_al(_Out, _Idx, _Al); - _RERAISE; - _CATCH_END + _Guard._Dismiss(); } } else if constexpr (_Use_memset_value_construct_v<_Ty*> && _Uses_default_construct<_Alloc, _Ty*>::value) { (void) _Al; - if (_Size > 0) { - _Zero_range(_Out, _Out + _Size); - } + _Zero_range(_Out, _Out + _Size); } else { _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; for (size_t _Count = 0; _Count < _Size; ++_Count) { @@ -1959,18 +1982,13 @@ template void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Size, const _Ty& _Val, _Alloc& _Al) { if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _TRY_BEGIN + _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); - _CATCH_ALL - _Reverse_destroy_multidimensional_n_al(_Out, _Idx, _Al); - _RERAISE; - _CATCH_END + _Guard._Dismiss(); } } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { (void) _Al; - if (_Size > 0) { - _CSTD memset(_Out, static_cast(_Val), static_cast(_Size)); - } + _CSTD memset(_Out, static_cast(_Val), _Size); } else { _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; for (size_t _Count = 0; _Count < _Size; ++_Count) { From 76a8e2c1b6a498bab091b0edbfe8490006cc17da Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 12 Mar 2020 23:10:38 -0700 Subject: [PATCH 40/52] Drop an unused constructor, use CTAD for guards. --- stl/inc/memory | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index f5a83341473..b3640c9474e 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1572,8 +1572,6 @@ struct _Uninitialized_rev_destroying_backout { explicit _Uninitialized_rev_destroying_backout(_NoThrowIt _Dest) : _First(_Dest), _Last(_Dest) {} - _Uninitialized_rev_destroying_backout(_NoThrowIt _First_, _NoThrowIt _Last_) : _First(_First_), _Last(_Last_) {} - _Uninitialized_rev_destroying_backout(const _Uninitialized_rev_destroying_backout&) = delete; _Uninitialized_rev_destroying_backout& operator=(const _Uninitialized_rev_destroying_backout&) = delete; @@ -1643,7 +1641,7 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ } else if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { _Copy_memmove(_In, _In + _Size, _Out); } else { - _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + _Uninitialized_rev_destroying_backout _Backout{_Out}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(_In[_Idx]); } @@ -1662,7 +1660,7 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si } else if constexpr (_Use_memset_value_construct_v<_Ty*>) { _Zero_range(_Out, _Out + _Size); } else { - _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + _Uninitialized_rev_destroying_backout _Backout{_Out}; for (size_t _Count = 0; _Count < _Size; ++_Count) { _Backout._Emplace_back(); } @@ -1681,7 +1679,7 @@ void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { _CSTD memset(_Out, static_cast(_Val), _Size); } else { - _Uninitialized_rev_destroying_backout<_Ty*> _Backout{_Out}; + _Uninitialized_rev_destroying_backout _Backout{_Out}; for (size_t _Count = 0; _Count < _Size; ++_Count) { _Backout._Emplace_back(_Val); } @@ -1950,7 +1948,7 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out (void) _Al; _Copy_memmove(_In, _In + _Size, _Out); } else { - _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(_In[_Idx]); } @@ -1970,7 +1968,7 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const (void) _Al; _Zero_range(_Out, _Out + _Size); } else { - _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; for (size_t _Count = 0; _Count < _Size; ++_Count) { _Backout._Emplace_back(); } @@ -1990,7 +1988,7 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si (void) _Al; _CSTD memset(_Out, static_cast(_Val), _Size); } else { - _Uninitialized_rev_destroying_backout_al<_Alloc> _Backout{_Out, _Al}; + _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; for (size_t _Count = 0; _Count < _Size; ++_Count) { _Backout._Emplace_back(_Val); } From 1c9328ecdef04f2874dd9346c1d50aa8e97d6440 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 12 Mar 2020 23:11:46 -0700 Subject: [PATCH 41/52] Extract `constexpr size_t _Align`, use injected-class-names. --- stl/inc/memory | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index b3640c9474e..ec3ce03d81b 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1713,8 +1713,8 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), - (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array)); + using _Storage = aligned_storage_t<_Align, _Align>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -1748,8 +1748,8 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - using _Storage = aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>)), - (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array<_Ty>))>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array)); + using _Storage = aligned_storage_t<_Align, _Align>; this->~_Ref_count_unbounded_array(); delete[] reinterpret_cast<_Storage*>(this); } @@ -2033,9 +2033,8 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - constexpr size_t _Max_alignment = - (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc<_Ty, _Alloc>)); - using _Storage = aligned_storage_t<_Max_alignment, _Max_alignment>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc)); + using _Storage = aligned_storage_t<_Align, _Align>; _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); this->~_Ref_count_unbounded_array_alloc(); allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), @@ -2105,9 +2104,9 @@ _NODISCARD template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array<_Ty>; - using _Storage = - aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + using _Refc = _Ref_count_unbounded_array<_Ty>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); + using _Storage = aligned_storage_t<_Align, _Align>; const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); @@ -2126,9 +2125,9 @@ template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array<_Ty>; - using _Storage = - aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + using _Refc = _Ref_count_unbounded_array<_Ty>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); + using _Storage = aligned_storage_t<_Align, _Align>; const auto _Rx = reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); @@ -2191,9 +2190,9 @@ template _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - using _Storage = - aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); + using _Storage = aligned_storage_t<_Align, _Align>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); @@ -2213,9 +2212,9 @@ template _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - using _Storage = - aligned_storage_t<(_STD max)(alignof(_Ty), alignof(_Refc)), (_STD max)(alignof(_Ty), alignof(_Refc))>; + using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; + constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); + using _Storage = aligned_storage_t<_Align, _Align>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); size_t _Size = _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); From 25d450ff15d49de29081637235913b397ae92261 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 12 Mar 2020 23:12:50 -0700 Subject: [PATCH 42/52] `_Allocate_flexible_array` refactoring, part 1. This carefully performs multiplication and addition overflow checks, and it avoids the use of `new[]` with aligned_storage_t that was emitting buffer overrun warnings. The new strategy is to give `_Ref_count_unbounded_array` storage for one element, and simply allocate additional space (via plain ::operator new) for additional elements if necessary. We need a bit of extra logic for alignment, performed with bitwise operations here (to avoid dividing and multiplying, even by a constant power of 2). (The concern is that if the refcount control block has an alignment of 8, and the elements have a size like 1, then the overall space requested might be an odd number like 1729, which might cause ::operator new to think that it doesn't need to return 8-aligned storage. By rounding up to the maximum alignment of the control block and the element, we avoid that issue.) This doesn't yet use an RAII guard for ::operator delete, but I plan to do so in the near future. This uses a non-_Ugly typedef element_type in internal code. This is slightly non-conventional, but safe (because it's a Standard typedef in shared_ptr, it can't be macroized). There's some existing precedent for this, and I wanted to reinforce that "this is the usual element_type definition that you've seen elsewhere". Part 2 will extend this to the allocator control blocks. --- stl/inc/memory | 79 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 31 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index ec3ce03d81b..ee39be6b039 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1564,6 +1564,28 @@ _NODISCARD constexpr _Ty _Div_ceil(const _Ty _Val1, const _Ty _Val2) noexcept { return (_Val1 + _Val2 - 1) / _Val2; // ***FIXME*** OVERFLOW } +template +_NODISCARD _Refc* _Allocate_flexible_array(const size_t _Count) { + size_t _Bytes = sizeof(_Refc); // contains storage for one element + + if (_Count > 1) { + using element_type = typename _Refc::element_type; + constexpr size_t _Align = (_STD max)(alignof(_Refc), alignof(element_type)); + + const size_t _Extra_bytes = _Get_size_of_n(_Count - 1); // check multiplication overflow + + if (_Extra_bytes > static_cast(-1) - _Bytes - (_Align - 1)) { // assume worst case alignment adjustment + _Throw_bad_array_new_length(); // addition overflow + } + + _Bytes += _Extra_bytes; + + _Bytes = (_Bytes + _Align - 1) & ~(_Align - 1); + } + + return static_cast<_Refc*>(::operator new(_Bytes)); +} + template struct _Uninitialized_rev_destroying_backout { // struct to undo partially constructed ranges in _Uninitialized_xxx algorithms @@ -1692,31 +1714,34 @@ template >> class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array with trivial destruction in control block, no allocator public: + using element_type = remove_extent_t<_Ty>; + explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Count); } - explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) : _Ref_count_base() { + explicit _Ref_count_unbounded_array(const size_t _Count, const element_type& _Val) : _Ref_count_base() { _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Count, _Val); } - ~_Ref_count_unbounded_array() = default; // nothing to do, _Ty is trivially destructible + ~_Ref_count_unbounded_array() {} // nothing to do, _Ty is trivially destructible auto _Get_ptr() { - return reinterpret_cast*>( - reinterpret_cast(this) + _Div_ceil(sizeof(*this), alignof(_Ty)) * alignof(_Ty)); + return _STD addressof(_Storage._Value); } private: + union { + _Wrap _Storage; // flexible array must be last member + }; + virtual void _Destroy() noexcept override { // destroy managed resource // nothing to do, _Ty is trivially destructible } virtual void _Delete_this() noexcept override { // destroy self - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array)); - using _Storage = aligned_storage_t<_Align, _Align>; this->~_Ref_count_unbounded_array(); - delete[] reinterpret_cast<_Storage*>(this); + ::operator delete(static_cast(this)); } }; @@ -1724,34 +1749,37 @@ template class _Ref_count_unbounded_array<_Ty, false> : public _Ref_count_base { // handle reference counting for unbounded array with non-trivial destruction in control block, no allocator public: + using element_type = remove_extent_t<_Ty>; + explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); } - explicit _Ref_count_unbounded_array(const size_t _Count, const remove_extent_t<_Ty>& _Val) + explicit _Ref_count_unbounded_array(const size_t _Count, const element_type& _Val) : _Ref_count_base(), _Size(_Count) { _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Size, _Val); } - ~_Ref_count_unbounded_array() = default; // nothing to do, _Storage was already destroyed in _Destroy + ~_Ref_count_unbounded_array() {} // nothing to do, _Storage was already destroyed in _Destroy auto _Get_ptr() { - return reinterpret_cast*>( - reinterpret_cast(this) + _Div_ceil(sizeof(*this), alignof(_Ty)) * alignof(_Ty)); + return _STD addressof(_Storage._Value); } private: size_t _Size; + union { + _Wrap _Storage; // flexible array must be last member + }; + virtual void _Destroy() noexcept override { // destroy managed resource _Reverse_destroy_multidimensional_n(_Get_ptr(), _Size); } virtual void _Delete_this() noexcept override { // destroy self - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array)); - using _Storage = aligned_storage_t<_Align, _Align>; this->~_Ref_count_unbounded_array(); - delete[] reinterpret_cast<_Storage*>(this); + ::operator delete(static_cast(this)); } }; @@ -2099,21 +2127,15 @@ _NODISCARD } #if _HAS_CXX20 -#pragma warning(push) // ***FIXME*** MUST INVESTIGATE BEFORE MERGING ***FIXME*** -#pragma warning(disable : 6386) // Buffer overrun while writing to '_Rx' template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array<_Ty>; - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); - using _Storage = aligned_storage_t<_Align, _Align>; - const auto _Rx = - reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); + using _Refc = _Ref_count_unbounded_array<_Ty>; + const auto _Rx = _Allocate_flexible_array<_Refc>(_Count); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Count); _CATCH_ALL - delete[] reinterpret_cast<_Storage*>(_Rx); + ::operator delete(static_cast(_Rx)); _RERAISE; _CATCH_END shared_ptr<_Ty> _Ret; @@ -2125,23 +2147,18 @@ template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array - using _Refc = _Ref_count_unbounded_array<_Ty>; - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); - using _Storage = aligned_storage_t<_Align, _Align>; - const auto _Rx = - reinterpret_cast<_Refc*>(new _Storage[_Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Div_ceil(sizeof(_Refc), sizeof(_Storage))]); + using _Refc = _Ref_count_unbounded_array<_Ty>; + const auto _Rx = _Allocate_flexible_array<_Refc>(_Count); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Count, _Val); _CATCH_ALL - delete[] reinterpret_cast<_Storage*>(_Rx); + ::operator delete(static_cast(_Rx)); _RERAISE; _CATCH_END shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; } -#pragma warning(pop) // ***FIXME*** MUST INVESTIGATE BEFORE MERGING ***FIXME*** template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared() { From 0d8aae35359529b55c98ee96b3f539234988e7fc Mon Sep 17 00:00:00 2001 From: Adam Date: Tue, 17 Mar 2020 12:02:28 +0100 Subject: [PATCH 43/52] Correct arguments in _Uses_default_destroy --- stl/inc/memory | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index ee39be6b039..84f9bf4f65f 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -2053,9 +2053,10 @@ private: ~_Ref_count_unbounded_array_alloc() = default; // nothing to do; _Storage._Value already destroyed by _Destroy() virtual void _Destroy() noexcept override { // destroy managed resource + using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; if constexpr (!conjunction_v>, - _Uses_default_destroy<_Alloc, _Ty*>>) { - _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + _Uses_default_destroy<_Rebound, remove_all_extents_t<_Ty>*>>) { + _Rebound _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } } @@ -2097,8 +2098,10 @@ private: } virtual void _Destroy() noexcept override { // destroy managed resource - if constexpr (!conjunction_v, _Uses_default_destroy<_Alloc, _Ty*>>) { - _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>> _Alty(this->_Get_val()); + using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; + if constexpr (!conjunction_v, + _Uses_default_destroy<_Rebound, remove_all_extents_t<_Ty>*>>) { + _Rebound _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); } } From a39cd1e30590f8080d44302317a4586a377dde6e Mon Sep 17 00:00:00 2001 From: Adam Date: Wed, 18 Mar 2020 11:14:05 +0100 Subject: [PATCH 44/52] Correct allocator in _Uses_default_destroy --- stl/inc/memory | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 84f9bf4f65f..1d356d6c568 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -2055,7 +2055,7 @@ private: virtual void _Destroy() noexcept override { // destroy managed resource using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; if constexpr (!conjunction_v>, - _Uses_default_destroy<_Rebound, remove_all_extents_t<_Ty>*>>) { + _Uses_default_destroy, remove_all_extents_t<_Ty>*>>) { _Rebound _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } @@ -2100,7 +2100,7 @@ private: virtual void _Destroy() noexcept override { // destroy managed resource using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; if constexpr (!conjunction_v, - _Uses_default_destroy<_Rebound, remove_all_extents_t<_Ty>*>>) { + _Uses_default_destroy, remove_all_extents_t<_Ty>*>>) { _Rebound _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); } From 45742a44baf0ded72124c454d03260e6456196d8 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 18 Mar 2020 18:14:00 -0700 Subject: [PATCH 45/52] `_Allocate_flexible_array` refactoring, part 2. This extends the refactoring to allocate_shared. It uses a "hybrid" approach, where the control block contains a union of one element (treated as a flexible array), giving the control block proper alignment, but storage for the control block is allocated as a sequence of `aligned_storage_t<_Align, _Align>` elements. This should resolve all overflow issues. Overflow checking is controllable because we don't need it during cleanup. Add comments citing N4849 [class.dtor]/7, explaining why these destructors must be defined with `{}` instead of `= default;`. --- stl/inc/memory | 135 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 45 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index a025b0e2f97..15b14b2dfa9 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1542,6 +1542,10 @@ public: ~_Ref_count_obj2() { // nothing to do, _Storage._Value was already destroyed in _Destroy + + // N4849 [class.dtor]/7: + // "A defaulted destructor for a class X is defined as deleted if: + // X is a union-like class that has a variant member with a non-trivial destructor" } union { @@ -1559,23 +1563,27 @@ private: }; #if _HAS_CXX20 -template -_NODISCARD constexpr _Ty _Div_ceil(const _Ty _Val1, const _Ty _Val2) noexcept { - return (_Val1 + _Val2 - 1) / _Val2; // ***FIXME*** OVERFLOW -} +enum class _Check_overflow : bool { _No, _Yes }; + +template +_NODISCARD size_t _Calculate_bytes_for_flexible_array(const size_t _Count) noexcept(_Check == _Check_overflow::_No) { + constexpr size_t _Align = alignof(_Refc); -template -_NODISCARD _Refc* _Allocate_flexible_array(const size_t _Count) { size_t _Bytes = sizeof(_Refc); // contains storage for one element if (_Count > 1) { - using element_type = typename _Refc::element_type; - constexpr size_t _Align = (_STD max)(alignof(_Refc), alignof(element_type)); + using _Element_type = typename _Refc::_Element_type; - const size_t _Extra_bytes = _Get_size_of_n(_Count - 1); // check multiplication overflow + size_t _Extra_bytes; - if (_Extra_bytes > static_cast(-1) - _Bytes - (_Align - 1)) { // assume worst case alignment adjustment - _Throw_bad_array_new_length(); // addition overflow + if constexpr (_Check == _Check_overflow::_Yes) { + _Extra_bytes = _Get_size_of_n(_Count - 1); // check multiplication overflow + + if (_Extra_bytes > static_cast(-1) - _Bytes - (_Align - 1)) { // assume worst case adjustment + _Throw_bad_array_new_length(); // addition overflow + } + } else { + _Extra_bytes = sizeof(_Element_type) * (_Count - 1); } _Bytes += _Extra_bytes; @@ -1583,6 +1591,17 @@ _NODISCARD _Refc* _Allocate_flexible_array(const size_t _Count) { _Bytes = (_Bytes + _Align - 1) & ~(_Align - 1); } +#ifdef _ENABLE_STL_INTERNAL_CHECK + using _Storage = aligned_storage_t<_Align, _Align>; + _STL_INTERNAL_CHECK(_Bytes % sizeof(_Storage) == 0); +#endif // _ENABLE_STL_INTERNAL_CHECK + + return _Bytes; +} + +template +_NODISCARD _Refc* _Allocate_flexible_array(const size_t _Count) { + const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); return static_cast<_Refc*>(::operator new(_Bytes)); } @@ -1714,27 +1733,31 @@ template >> class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array with trivial destruction in control block, no allocator public: - using element_type = remove_extent_t<_Ty>; + using _Element_type = remove_extent_t<_Ty>; explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Count); } - explicit _Ref_count_unbounded_array(const size_t _Count, const element_type& _Val) : _Ref_count_base() { + explicit _Ref_count_unbounded_array(const size_t _Count, const _Element_type& _Val) : _Ref_count_base() { _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Count, _Val); } - ~_Ref_count_unbounded_array() {} // nothing to do, _Ty is trivially destructible - auto _Get_ptr() { return _STD addressof(_Storage._Value); } private: union { - _Wrap _Storage; // flexible array must be last member + _Wrap<_Element_type> _Storage; // flexible array must be last member }; + ~_Ref_count_unbounded_array() { + // nothing to do, _Ty is trivially destructible + + // See N4849 [class.dtor]/7. + } + virtual void _Destroy() noexcept override { // destroy managed resource // nothing to do, _Ty is trivially destructible } @@ -1749,19 +1772,17 @@ template class _Ref_count_unbounded_array<_Ty, false> : public _Ref_count_base { // handle reference counting for unbounded array with non-trivial destruction in control block, no allocator public: - using element_type = remove_extent_t<_Ty>; + using _Element_type = remove_extent_t<_Ty>; explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { _Uninitialized_value_construct_multidimensional_n(_Get_ptr(), _Size); } - explicit _Ref_count_unbounded_array(const size_t _Count, const element_type& _Val) + explicit _Ref_count_unbounded_array(const size_t _Count, const _Element_type& _Val) : _Ref_count_base(), _Size(_Count) { _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Size, _Val); } - ~_Ref_count_unbounded_array() {} // nothing to do, _Storage was already destroyed in _Destroy - auto _Get_ptr() { return _STD addressof(_Storage._Value); } @@ -1770,9 +1791,15 @@ private: size_t _Size; union { - _Wrap _Storage; // flexible array must be last member + _Wrap<_Element_type> _Storage; // flexible array must be last member }; + ~_Ref_count_unbounded_array() { + // nothing to do, _Storage was already destroyed in _Destroy + + // See N4849 [class.dtor]/7. + } + virtual void _Destroy() noexcept override { // destroy managed resource _Reverse_destroy_multidimensional_n(_Get_ptr(), _Size); } @@ -1794,15 +1821,17 @@ public: _Uninitialized_fill_multidimensional_n(_Storage._Value, extent_v<_Ty>, _Val); } - ~_Ref_count_bounded_array() { - // nothing to do, _Storage was already destroyed in _Destroy - } - union { _Wrap<_Ty> _Storage; }; private: + ~_Ref_count_bounded_array() { + // nothing to do, _Storage was already destroyed in _Destroy + + // See N4849 [class.dtor]/7. + } + virtual void _Destroy() noexcept override { // destroy managed resource _Destroy_in_place(_Storage); // not _Storage._Value, see N4849 [expr.prim.id.dtor] } @@ -1873,6 +1902,8 @@ public: private: ~_Ref_count_obj_alloc2() { // nothing to do; _Storage._Value already destroyed by _Destroy() + + // See N4849 [class.dtor]/7. } virtual void _Destroy() noexcept override { // destroy managed resource @@ -2029,32 +2060,40 @@ template class __declspec(empty_bases) _Ref_count_unbounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { // handle reference counting for unbounded array in control block, allocator public: + using _Element_type = remove_extent_t<_Ty>; + explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, const size_t _Count) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); _Uninitialized_value_construct_multidimensional_n_al(_Get_ptr(), _Size, _Alty); } - explicit _Ref_count_unbounded_array_alloc( - const _Alloc& _Al_arg, const size_t _Count, const remove_extent_t<_Ty>& _Val) + explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, const size_t _Count, const _Element_type& _Val) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); _Uninitialized_fill_multidimensional_n_al(_Get_ptr(), _Size, _Val, _Alty); } auto _Get_ptr() { - return reinterpret_cast*>( - reinterpret_cast(this) + _Div_ceil(sizeof(*this), alignof(_Ty)) * alignof(_Ty)); + return _STD addressof(_Storage._Value); } private: size_t _Size; - ~_Ref_count_unbounded_array_alloc() = default; // nothing to do; _Storage._Value already destroyed by _Destroy() + union { + _Wrap<_Element_type> _Storage; // flexible array must be last member + }; + + ~_Ref_count_unbounded_array_alloc() { + // nothing to do; _Storage._Value already destroyed by _Destroy() + + // See N4849 [class.dtor]/7. + } virtual void _Destroy() noexcept override { // destroy managed resource using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; - if constexpr (!conjunction_v>, + if constexpr (!conjunction_v, _Uses_default_destroy, remove_all_extents_t<_Ty>*>>) { _Rebound _Alty(this->_Get_val()); _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); @@ -2062,13 +2101,17 @@ private: } virtual void _Delete_this() noexcept override { // destroy self - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Ref_count_unbounded_array_alloc)); + constexpr size_t _Align = alignof(_Ref_count_unbounded_array_alloc); using _Storage = aligned_storage_t<_Align, _Align>; + _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); + const size_t _Bytes = + _Calculate_bytes_for_flexible_array<_Ref_count_unbounded_array_alloc, _Check_overflow::_No>(_Size); + const size_t _Storage_units = _Bytes / sizeof(_Storage); + this->~_Ref_count_unbounded_array_alloc(); - allocator_traits<_Rebind_alloc_t<_Alloc, _Storage>>::deallocate(_Al, reinterpret_cast<_Storage*>(this), - _Div_ceil(_Size * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) - + _Div_ceil(sizeof(*this), sizeof(_Storage))); + + _Al.deallocate(reinterpret_cast<_Storage*>(this), _Storage_units); } }; @@ -2095,6 +2138,8 @@ public: private: ~_Ref_count_bounded_array_alloc() { // nothing to do; _Storage._Value already destroyed by _Destroy() + + // See N4849 [class.dtor]/7. } virtual void _Destroy() noexcept override { // destroy managed resource @@ -2211,16 +2256,16 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shar const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); + constexpr size_t _Align = alignof(_Refc); using _Storage = aligned_storage_t<_Align, _Align>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); - size_t _Size = - _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Size)); + const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); + const size_t _Storage_units = _Bytes / sizeof(_Storage); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Storage_units)); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Al, _Count); _CATCH_ALL - _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Size); + _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Storage_units); _RERAISE; _CATCH_END shared_ptr<_Ty> _Ret; @@ -2233,16 +2278,16 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shar const _Alloc& _Al, const size_t _Count, const remove_extent_t<_Ty>& _Val) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; - constexpr size_t _Align = (_STD max)(alignof(_Ty), alignof(_Refc)); + constexpr size_t _Align = alignof(_Refc); using _Storage = aligned_storage_t<_Align, _Align>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); - size_t _Size = - _Div_ceil(_Count * sizeof(remove_extent_t<_Ty>), sizeof(_Storage)) + _Div_ceil(sizeof(_Refc), sizeof(_Storage)); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Size)); + const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); + const size_t _Storage_units = _Bytes / sizeof(_Storage); + const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Storage_units)); _TRY_BEGIN ::new (static_cast(_Rx)) _Refc(_Al, _Count, _Val); _CATCH_ALL - _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Size); + _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Storage_units); _RERAISE; _CATCH_END shared_ptr<_Ty> _Ret; From 21d9c480bd8f38c6f4d0fcd36653e2c2e17e9ee7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Fri, 20 Mar 2020 02:31:45 -0700 Subject: [PATCH 46/52] Address all remaining code review feedback. Replace aligned_storage_t with _Alignas_storage_unit. Comment a meow_copy call within a meow_fill function. Use RAII guards for global delete and allocator deallocate. Respect fancy pointers. Use more CTAD. --- stl/inc/memory | 83 +++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 31 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 15b14b2dfa9..9447c409275 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1563,6 +1563,11 @@ private: }; #if _HAS_CXX20 +template +struct _Alignas_storage_unit { + alignas(_Align) char _Space[_Align]; +}; + enum class _Check_overflow : bool { _No, _Yes }; template @@ -1592,7 +1597,7 @@ _NODISCARD size_t _Calculate_bytes_for_flexible_array(const size_t _Count) noexc } #ifdef _ENABLE_STL_INTERNAL_CHECK - using _Storage = aligned_storage_t<_Align, _Align>; + using _Storage = _Alignas_storage_unit<_Align>; _STL_INTERNAL_CHECK(_Bytes % sizeof(_Storage) == 0); #endif // _ENABLE_STL_INTERNAL_CHECK @@ -2040,7 +2045,7 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; - _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); + _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); // intentionally copy, not fill _Guard._Dismiss(); } } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { @@ -2102,7 +2107,7 @@ private: virtual void _Delete_this() noexcept override { // destroy self constexpr size_t _Align = alignof(_Ref_count_unbounded_array_alloc); - using _Storage = aligned_storage_t<_Align, _Align>; + using _Storage = _Alignas_storage_unit<_Align>; _Rebind_alloc_t<_Alloc, _Storage> _Al(this->_Get_val()); const size_t _Bytes = @@ -2175,17 +2180,24 @@ _NODISCARD } #if _HAS_CXX20 +struct _Global_delete_guard { + void* _Target; + + ~_Global_delete_guard() { + if (_Target) { + ::operator delete(_Target); + } + } +}; + template _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; const auto _Rx = _Allocate_flexible_array<_Refc>(_Count); - _TRY_BEGIN + _Global_delete_guard _Guard{_Rx}; ::new (static_cast(_Rx)) _Refc(_Count); - _CATCH_ALL - ::operator delete(static_cast(_Rx)); - _RERAISE; - _CATCH_END + _Guard._Target = nullptr; shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; @@ -2197,12 +2209,9 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; const auto _Rx = _Allocate_flexible_array<_Refc>(_Count); - _TRY_BEGIN + _Global_delete_guard _Guard{_Rx}; ::new (static_cast(_Rx)) _Refc(_Count, _Val); - _CATCH_ALL - ::operator delete(static_cast(_Rx)); - _RERAISE; - _CATCH_END + _Guard._Target = nullptr; shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; @@ -2251,23 +2260,38 @@ _NODISCARD } #if _HAS_CXX20 +template +struct _Allocate_n_ptr { + _Alloc& _Al; + _Alloc_ptr_t<_Alloc> _Ptr; + size_t _Nx; + + _Allocate_n_ptr(_Alloc& _Al_, const size_t _Nx_) : _Al(_Al_), _Ptr(_Al_.allocate(_Nx_)), _Nx(_Nx_) {} + + ~_Allocate_n_ptr() { + if (_Ptr) { + _Al.deallocate(_Ptr, _Nx); + } + } + + _Allocate_n_ptr(const _Allocate_n_ptr&) = delete; + _Allocate_n_ptr& operator=(const _Allocate_n_ptr&) = delete; +}; + template _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared( const _Alloc& _Al, const size_t _Count) { // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; constexpr size_t _Align = alignof(_Refc); - using _Storage = aligned_storage_t<_Align, _Align>; + using _Storage = _Alignas_storage_unit<_Align>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); const size_t _Storage_units = _Bytes / sizeof(_Storage); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Storage_units)); - _TRY_BEGIN + _Allocate_n_ptr _Guard{_Rebound, _Storage_units}; + const auto _Rx = reinterpret_cast<_Refc*>(_Unfancy(_Guard._Ptr)); ::new (static_cast(_Rx)) _Refc(_Al, _Count); - _CATCH_ALL - _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Storage_units); - _RERAISE; - _CATCH_END + _Guard._Ptr = nullptr; shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; @@ -2279,17 +2303,14 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shar // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array_alloc, _Alloc>; constexpr size_t _Align = alignof(_Refc); - using _Storage = aligned_storage_t<_Align, _Align>; + using _Storage = _Alignas_storage_unit<_Align>; _Rebind_alloc_t<_Alloc, _Storage> _Rebound(_Al); const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); const size_t _Storage_units = _Bytes / sizeof(_Storage); - const auto _Rx = reinterpret_cast<_Refc*>(_Rebound.allocate(_Storage_units)); - _TRY_BEGIN + _Allocate_n_ptr _Guard{_Rebound, _Storage_units}; + const auto _Rx = reinterpret_cast<_Refc*>(_Unfancy(_Guard._Ptr)); ::new (static_cast(_Rx)) _Refc(_Al, _Count, _Val); - _CATCH_ALL - _Rebound.deallocate(reinterpret_cast<_Storage*>(_Rx), _Storage_units); - _RERAISE; - _CATCH_END + _Guard._Ptr = nullptr; shared_ptr<_Ty> _Ret; _Ret._Set_ptr_rep_and_enable_shared(_Rx->_Get_ptr(), _Rx); return _Ret; @@ -2301,9 +2322,9 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); - _Alloc_construct_ptr<_Alblock> _Constructor{_Rebound}; + _Alloc_construct_ptr _Constructor{_Rebound}; _Constructor._Allocate(); - ::new (static_cast(_Constructor._Ptr)) _Refc(_Al); + ::new (static_cast(_Unfancy(_Constructor._Ptr))) _Refc(_Al); shared_ptr<_Ty> _Ret; const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); @@ -2317,9 +2338,9 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> allocate_shared using _Refc = _Ref_count_bounded_array_alloc, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refc>; _Alblock _Rebound(_Al); - _Alloc_construct_ptr<_Alblock> _Constructor{_Rebound}; + _Alloc_construct_ptr _Constructor{_Rebound}; _Constructor._Allocate(); - ::new (static_cast(_Constructor._Ptr)) _Refc(_Al, _Val); + ::new (static_cast(_Unfancy(_Constructor._Ptr))) _Refc(_Al, _Val); shared_ptr<_Ty> _Ret; const auto _Ptr = static_cast*>(_Constructor._Ptr->_Storage._Value); _Ret._Set_ptr_rep_and_enable_shared(_Ptr, _Unfancy(_Constructor._Release())); From c8b6d32e37aad72ee940684436d4a1c23fcef4bb Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 1 Apr 2020 18:00:24 -0700 Subject: [PATCH 47/52] More code review improvements. Add `noexcept` to internal machinery. Instead of testing `(rank_v<_Ty>) > 0`, simply test `is_array_v<_Ty>`. Change `_Reverse_destroy_multidimensional_n_guard` to be an aggregate. (Note that Clang 10 doesn't support CTAD for aggregates.) Rework the optimization metaprogramming in `_Uninitialized_copy_multidimensional`. First, `_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial` was incorrect. This is because `_Ptr_copy_cat` checks `is_trivially_assignable_v`, which will be false when `_Ty` is an array. Instead, we should test `is_trivial_v<_Ty>`. (We don't need the rest of what `_Ptr_copy_cat` does, because we're not working with user-defined iterators, and our source and destination are the same type.) Second, `is_trivial_v<_Ty>` can be the first thing we test; when we're working with trivial elements, we can perform a single `_Copy_memmove`, regardless of whether these are single-dimensional or multi-dimensional arrays. Finally, for `is_array_v<_Ty>`, it was strange (although correct) to construct an RAII guard for each iteration of the loop. We can lift this out and simply update the guard's index. (Same transformation for the following algorithms.) Similarly for `_Uninitialized_value_construct_multidimensional_n`, `_Use_memset_value_construct_v<_Ty*>` was incorrect as it checks `is_scalar` which is false for arrays. We need to use `remove_all_extents_t<_Ty>`, which I've been referring to as `_Item`. Also similarly, we can perform this `_Zero_range` optimization at the top level. Finally, we should consistently use `_Idx` instead of `_Count` to iterate (also changed below). In `_Uninitialized_fill_multidimensional_n`, add the `// intentionally copy, not fill` comment (previously applied to the allocator version). Mark `_Get_ptr()` as `_NODISCARD` and `noexcept`. Change pre-existing code for consistency: upgrade `_Ref_count_obj_alloc2` to `_Ref_count_obj_alloc3`. The difference is that we store _Rebind_alloc_t<_Alloc, _Ty> so we can directly use it later. (We still need to rebind for `_Delete_this`.) Also add a `static_assert` verifying that we're following the Standard's `remove_cv_t` wording. Change `_Reverse_destroy_multidimensional_n_al_guard` and its associated algorithms similarly to the non-allocator versions. In `_Uninitialized_copy_multidimensional_al`, change `_Uses_default_construct<_Alloc, _Ty*, _Ty>` to `_Uses_default_construct<_Alloc, _Item*, const _Item&>`. This is because the provided `_Alloc` is for the `_Item` (aka `remove_all_extents_t<_Ty>`) that we ultimately construct from a const lvalue. In `_Uninitialized_value_construct_multidimensional_n_al`, similarly change the `_Zero_range` metaprogramming. In `_Uninitialized_fill_multidimensional_n_al`, slightly adjust `_Uses_default_construct<_Alloc, _Ty*, _Ty>` to `_Uses_default_construct<_Alloc, _Ty*, const _Ty&>` because we construct from a const lvalue, and that distinction could be important. Change `_Ref_count_unbounded_array_alloc` to store `_Rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>` so we don't need to rebind it later. Also `static_assert` `remove_cv_t`. Adjust the metaprogramming in `_Destroy()`. `is_trivially_destructible<_Element_type>` was correct (`_Element_type` removes the unbounded array, and the type trait "recurses" to the non-array item), but `is_trivially_destructible<_Item>` is what we're ultimately interested in, and will be more consistent with other control blocks. Also, `_Rebound` is never a reference now, and we have the `_Item` typedef. Fix `_Ref_count_bounded_array_alloc` comment; "for object" should be "for bounded array". Similarly change its implementation. Here, `is_trivially_destructible<_Ty>` was correct (`_Ty` is a bounded array), but`is_trivially_destructible<_Item>` lets us be consistent with the unbounded array control block. --- stl/inc/memory | 240 +++++++++++++++++++++++-------------------------- 1 file changed, 114 insertions(+), 126 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 5d2955fdd5f..5750de3d7b6 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1616,7 +1616,7 @@ struct _Uninitialized_rev_destroying_backout { _NoThrowIt _First; _NoThrowIt _Last; - explicit _Uninitialized_rev_destroying_backout(_NoThrowIt _Dest) : _First(_Dest), _Last(_Dest) {} + explicit _Uninitialized_rev_destroying_backout(_NoThrowIt _Dest) noexcept : _First(_Dest), _Last(_Dest) {} _Uninitialized_rev_destroying_backout(const _Uninitialized_rev_destroying_backout&) = delete; _Uninitialized_rev_destroying_backout& operator=(const _Uninitialized_rev_destroying_backout&) = delete; @@ -1634,17 +1634,17 @@ struct _Uninitialized_rev_destroying_backout { ++_Last; } - _NoThrowIt _Release() { // suppress any exception handling backout and return _Last + _NoThrowIt _Release() noexcept { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } }; template -void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) { +void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) noexcept { while (_Size > 0) { --_Size; - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 + if constexpr (is_array_v<_Ty>) { _Reverse_destroy_multidimensional_n(_Arr[_Size], extent_v<_Ty>); } else { _Destroy_in_place(_Arr[_Size]); @@ -1653,39 +1653,27 @@ void _Reverse_destroy_multidimensional_n(_Ty* const _Arr, size_t _Size) { } template -class _Reverse_destroy_multidimensional_n_guard { -public: - _Reverse_destroy_multidimensional_n_guard(_Ty* const _Arr_, const size_t _Size_) noexcept - : _Arr(_Arr_), _Size(_Size_) {} - - void _Dismiss() noexcept { - _Arr = nullptr; - } +struct _Reverse_destroy_multidimensional_n_guard { + _Ty* _Target; + size_t _Index; ~_Reverse_destroy_multidimensional_n_guard() { - if (_Arr) { - _Reverse_destroy_multidimensional_n(_Arr, _Size); + if (_Target) { + _Reverse_destroy_multidimensional_n(_Target, _Index); } } - - _Reverse_destroy_multidimensional_n_guard(const _Reverse_destroy_multidimensional_n_guard&) = delete; - _Reverse_destroy_multidimensional_n_guard& operator=(const _Reverse_destroy_multidimensional_n_guard&) = delete; - -private: - _Ty* _Arr; - size_t _Size; }; template void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size]) { - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Reverse_destroy_multidimensional_n_guard _Guard{_Out, _Idx}; + if constexpr (is_trivial_v<_Ty>) { + _Copy_memmove(_In, _In + _Size, _Out); + } else if constexpr (is_array_v<_Ty>) { + _Reverse_destroy_multidimensional_n_guard<_Ty> _Guard{_Out, 0}; + for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { _Uninitialized_copy_multidimensional(_In[_Idx], _Out[_Idx]); - _Guard._Dismiss(); } - } else if constexpr (_Ptr_copy_cat<_Ty*, _Ty*>::_Really_trivial) { - _Copy_memmove(_In, _In + _Size, _Out); + _Guard._Target = nullptr; } else { _Uninitialized_rev_destroying_backout _Backout{_Out}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -1697,17 +1685,18 @@ void _Uninitialized_copy_multidimensional(const _Ty (&_In)[_Size], _Ty (&_Out)[_ template void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const size_t _Size) { - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Reverse_destroy_multidimensional_n_guard _Guard{_Out, _Idx}; + using _Item = remove_all_extents_t<_Ty>; + if constexpr (_Use_memset_value_construct_v<_Item*>) { + _Zero_range(_Out, _Out + _Size); + } else if constexpr (is_array_v<_Ty>) { + _Reverse_destroy_multidimensional_n_guard<_Ty> _Guard{_Out, 0}; + for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { _Uninitialized_value_construct_multidimensional_n(_Out[_Idx], extent_v<_Ty>); - _Guard._Dismiss(); } - } else if constexpr (_Use_memset_value_construct_v<_Ty*>) { - _Zero_range(_Out, _Out + _Size); + _Guard._Target = nullptr; } else { _Uninitialized_rev_destroying_backout _Backout{_Out}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(); } _Backout._Release(); @@ -1716,17 +1705,17 @@ void _Uninitialized_value_construct_multidimensional_n(_Ty* const _Out, const si template void _Uninitialized_fill_multidimensional_n(_Ty* const _Out, const size_t _Size, const _Ty& _Val) { - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Reverse_destroy_multidimensional_n_guard _Guard{_Out, _Idx}; - _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); - _Guard._Dismiss(); + if constexpr (is_array_v<_Ty>) { + _Reverse_destroy_multidimensional_n_guard<_Ty> _Guard{_Out, 0}; + for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { + _Uninitialized_copy_multidimensional(_Val, _Out[_Idx]); // intentionally copy, not fill } + _Guard._Target = nullptr; } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty>) { _CSTD memset(_Out, static_cast(_Val), _Size); } else { _Uninitialized_rev_destroying_backout _Backout{_Out}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(_Val); } _Backout._Release(); @@ -1748,7 +1737,7 @@ public: _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Count, _Val); } - auto _Get_ptr() { + _NODISCARD auto _Get_ptr() noexcept { return _STD addressof(_Storage._Value); } @@ -1788,7 +1777,7 @@ public: _Uninitialized_fill_multidimensional_n(_Get_ptr(), _Size, _Val); } - auto _Get_ptr() { + _NODISCARD auto _Get_ptr() noexcept { return _STD addressof(_Storage._Value); } @@ -1887,17 +1876,22 @@ protected: } }; -// CLASS TEMPLATE _Ref_count_obj_alloc2 +// CLASS TEMPLATE _Ref_count_obj_alloc3 template -class __declspec(empty_bases) _Ref_count_obj_alloc2 : public _Ebco_base<_Alloc>, public _Ref_count_base { +class __declspec(empty_bases) _Ref_count_obj_alloc3 : public _Ebco_base<_Rebind_alloc_t<_Alloc, _Ty>>, + public _Ref_count_base { // handle reference counting for object in control block, allocator +private: + static_assert(is_same_v<_Ty, remove_cv_t<_Ty>>, "allocate_shared should remove_cv_t"); + + using _Rebound = _Rebind_alloc_t<_Alloc, _Ty>; + public: template - explicit _Ref_count_obj_alloc2(const _Alloc& _Al_arg, _Types&&... _Args) - : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { - _Maybe_rebind_alloc_t<_Alloc, _Ty> _Alty(this->_Get_val()); - allocator_traits<_Rebind_alloc_t<_Alloc, _Ty>>::construct( - _Alty, _STD addressof(_Storage._Value), _STD forward<_Types>(_Args)...); + explicit _Ref_count_obj_alloc3(const _Alloc& _Al_arg, _Types&&... _Args) + : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { + allocator_traits<_Rebound>::construct( + this->_Get_val(), _STD addressof(_Storage._Value), _STD forward<_Types>(_Args)...); } union { @@ -1905,20 +1899,19 @@ public: }; private: - ~_Ref_count_obj_alloc2() { + ~_Ref_count_obj_alloc3() { // nothing to do; _Storage._Value already destroyed by _Destroy() // See N4849 [class.dtor]/7. } virtual void _Destroy() noexcept override { // destroy managed resource - _Maybe_rebind_alloc_t<_Alloc, _Ty> _Alty(this->_Get_val()); - allocator_traits<_Rebind_alloc_t<_Alloc, _Ty>>::destroy(_Alty, _STD addressof(_Storage._Value)); + allocator_traits<_Rebound>::destroy(this->_Get_val(), _STD addressof(_Storage._Value)); } virtual void _Delete_this() noexcept override { // destroy self - _Rebind_alloc_t<_Alloc, _Ref_count_obj_alloc2> _Al(this->_Get_val()); - this->~_Ref_count_obj_alloc2(); + _Rebind_alloc_t<_Alloc, _Ref_count_obj_alloc3> _Al(this->_Get_val()); + this->~_Ref_count_obj_alloc3(); _Deallocate_plain(_Al, this); } }; @@ -1932,7 +1925,8 @@ private: using pointer = _Alloc_ptr_t<_Alloc>; public: - _Uninitialized_rev_destroying_backout_al(pointer _Dest, _Alloc& _Al_) : _First(_Dest), _Last(_Dest), _Al(_Al_) {} + _Uninitialized_rev_destroying_backout_al(pointer _Dest, _Alloc& _Al_) noexcept + : _First(_Dest), _Last(_Dest), _Al(_Al_) {} _Uninitialized_rev_destroying_backout_al(const _Uninitialized_rev_destroying_backout_al&) = delete; _Uninitialized_rev_destroying_backout_al& operator=(const _Uninitialized_rev_destroying_backout_al&) = delete; @@ -1950,7 +1944,7 @@ public: ++_Last; } - pointer _Release() { // suppress any exception handling backout and return _Last + pointer _Release() noexcept { // suppress any exception handling backout and return _Last _First = _Last; return _Last; } @@ -1962,10 +1956,10 @@ private: }; template -void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Alloc& _Al) { +void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Alloc& _Al) noexcept { while (_Size > 0) { --_Size; - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 + if constexpr (is_array_v<_Ty>) { _Reverse_destroy_multidimensional_n_al(_Arr[_Size], extent_v<_Ty>, _Al); } else { allocator_traits<_Alloc>::destroy(_Al, _Arr + _Size); @@ -1974,43 +1968,30 @@ void _Reverse_destroy_multidimensional_n_al(_Ty* const _Arr, size_t _Size, _Allo } template -class _Reverse_destroy_multidimensional_n_al_guard { -public: - _Reverse_destroy_multidimensional_n_al_guard(_Ty* const _Arr_, const size_t _Size_, _Alloc& _Al_) noexcept - : _Arr(_Arr_), _Size(_Size_), _Al(_Al_) {} - - void _Dismiss() noexcept { - _Arr = nullptr; - } +struct _Reverse_destroy_multidimensional_n_al_guard { + _Ty* _Target; + size_t _Index; + _Alloc& _Al; ~_Reverse_destroy_multidimensional_n_al_guard() { - if (_Arr) { - _Reverse_destroy_multidimensional_n_al(_Arr, _Size, _Al); + if (_Target) { + _Reverse_destroy_multidimensional_n_al(_Target, _Index, _Al); } } - - _Reverse_destroy_multidimensional_n_al_guard(const _Reverse_destroy_multidimensional_n_al_guard&) = delete; - _Reverse_destroy_multidimensional_n_al_guard& operator=( // - const _Reverse_destroy_multidimensional_n_al_guard&) = delete; - -private: - _Ty* _Arr; - size_t _Size; - _Alloc& _Al; }; template void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out)[_Size], _Alloc& _Al) { - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; - _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); - _Guard._Dismiss(); - } - } else if constexpr (conjunction_v::_Really_trivial>, - _Uses_default_construct<_Alloc, _Ty*, _Ty>>) { + using _Item = remove_all_extents_t<_Ty>; + if constexpr (conjunction_v, _Uses_default_construct<_Alloc, _Item*, const _Item&>>) { (void) _Al; _Copy_memmove(_In, _In + _Size, _Out); + } else if constexpr (is_array_v<_Ty>) { + _Reverse_destroy_multidimensional_n_al_guard<_Ty, _Alloc> _Guard{_Out, 0, _Al}; + for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { + _Uninitialized_copy_multidimensional_al(_In[_Idx], _Out[_Idx], _Al); + } + _Guard._Target = nullptr; } else { _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { @@ -2022,18 +2003,19 @@ void _Uninitialized_copy_multidimensional_al(const _Ty (&_In)[_Size], _Ty (&_Out template void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const size_t _Size, _Alloc& _Al) { - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; - _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); - _Guard._Dismiss(); - } - } else if constexpr (_Use_memset_value_construct_v<_Ty*> && _Uses_default_construct<_Alloc, _Ty*>::value) { + using _Item = remove_all_extents_t<_Ty>; + if constexpr (_Use_memset_value_construct_v<_Item*> && _Uses_default_construct<_Alloc, _Item*>::value) { (void) _Al; _Zero_range(_Out, _Out + _Size); + } else if constexpr (is_array_v<_Ty>) { + _Reverse_destroy_multidimensional_n_al_guard<_Ty, _Alloc> _Guard{_Out, 0, _Al}; + for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { + _Uninitialized_value_construct_multidimensional_n_al(_Out[_Idx], extent_v<_Ty>, _Al); + } + _Guard._Target = nullptr; } else { _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(); } _Backout._Release(); @@ -2042,18 +2024,18 @@ void _Uninitialized_value_construct_multidimensional_n_al(_Ty* const _Out, const template void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Size, const _Ty& _Val, _Alloc& _Al) { - if constexpr ((rank_v<_Ty>) > 0) { // TRANSITION, LLVM-42404 - for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { - _Reverse_destroy_multidimensional_n_al_guard _Guard{_Out, _Idx, _Al}; + if constexpr (is_array_v<_Ty>) { + _Reverse_destroy_multidimensional_n_al_guard<_Ty, _Alloc> _Guard{_Out, 0, _Al}; + for (size_t& _Idx = _Guard._Index; _Idx < _Size; ++_Idx) { _Uninitialized_copy_multidimensional_al(_Val, _Out[_Idx], _Al); // intentionally copy, not fill - _Guard._Dismiss(); } - } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, _Ty>::value) { + _Guard._Target = nullptr; + } else if constexpr (_Fill_memset_is_safe<_Ty*, _Ty> && _Uses_default_construct<_Alloc, _Ty*, const _Ty&>::value) { (void) _Al; _CSTD memset(_Out, static_cast(_Val), _Size); } else { _Uninitialized_rev_destroying_backout_al _Backout{_Out, _Al}; - for (size_t _Count = 0; _Count < _Size; ++_Count) { + for (size_t _Idx = 0; _Idx < _Size; ++_Idx) { _Backout._Emplace_back(_Val); } _Backout._Release(); @@ -2062,24 +2044,30 @@ void _Uninitialized_fill_multidimensional_n_al(_Ty* const _Out, const size_t _Si // CLASS TEMPLATE _Ref_count_unbounded_array_alloc template -class __declspec(empty_bases) _Ref_count_unbounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { +class __declspec(empty_bases) _Ref_count_unbounded_array_alloc + : public _Ebco_base<_Rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>>, + public _Ref_count_base { // handle reference counting for unbounded array in control block, allocator +private: + static_assert(is_same_v<_Ty, remove_cv_t<_Ty>>, "allocate_shared should remove_cv_t"); + + using _Item = remove_all_extents_t<_Ty>; + using _Rebound = _Rebind_alloc_t<_Alloc, _Item>; + public: using _Element_type = remove_extent_t<_Ty>; explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, const size_t _Count) - : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { - _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); - _Uninitialized_value_construct_multidimensional_n_al(_Get_ptr(), _Size, _Alty); + : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base(), _Size(_Count) { + _Uninitialized_value_construct_multidimensional_n_al(_Get_ptr(), _Size, this->_Get_val()); } explicit _Ref_count_unbounded_array_alloc(const _Alloc& _Al_arg, const size_t _Count, const _Element_type& _Val) - : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base(), _Size(_Count) { - _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); - _Uninitialized_fill_multidimensional_n_al(_Get_ptr(), _Size, _Val, _Alty); + : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base(), _Size(_Count) { + _Uninitialized_fill_multidimensional_n_al(_Get_ptr(), _Size, _Val, this->_Get_val()); } - auto _Get_ptr() { + _NODISCARD auto _Get_ptr() noexcept { return _STD addressof(_Storage._Value); } @@ -2097,11 +2085,8 @@ private: } virtual void _Destroy() noexcept override { // destroy managed resource - using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; - if constexpr (!conjunction_v, - _Uses_default_destroy, remove_all_extents_t<_Ty>*>>) { - _Rebound _Alty(this->_Get_val()); - _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, _Alty); + if constexpr (!conjunction_v, _Uses_default_destroy<_Rebound, _Item*>>) { + _Reverse_destroy_multidimensional_n_al(_Get_ptr(), _Size, this->_Get_val()); } } @@ -2122,18 +2107,24 @@ private: // CLASS TEMPLATE _Ref_count_bounded_array_alloc template -class __declspec(empty_bases) _Ref_count_bounded_array_alloc : public _Ebco_base<_Alloc>, public _Ref_count_base { - // handle reference counting for object in control block, allocator +class __declspec(empty_bases) _Ref_count_bounded_array_alloc + : public _Ebco_base<_Rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>>, + public _Ref_count_base { + // handle reference counting for bounded array in control block, allocator +private: + static_assert(is_same_v<_Ty, remove_cv_t<_Ty>>, "allocate_shared should remove_cv_t"); + + using _Item = remove_all_extents_t<_Ty>; + using _Rebound = _Rebind_alloc_t<_Alloc, _Item>; + public: - explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { - _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); - _Uninitialized_value_construct_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); + explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { + _Uninitialized_value_construct_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, this->_Get_val()); } explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg, const remove_extent_t<_Ty>& _Val) - : _Ebco_base<_Alloc>(_Al_arg), _Ref_count_base() { - _Maybe_rebind_alloc_t<_Alloc, remove_cv_t>> _Alty(this->_Get_val()); - _Uninitialized_fill_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Val, _Alty); + : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { + _Uninitialized_fill_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Val, this->_Get_val()); } union { @@ -2148,11 +2139,8 @@ private: } virtual void _Destroy() noexcept override { // destroy managed resource - using _Rebound = _Maybe_rebind_alloc_t<_Alloc, remove_all_extents_t<_Ty>>; - if constexpr (!conjunction_v, - _Uses_default_destroy, remove_all_extents_t<_Ty>*>>) { - _Rebound _Alty(this->_Get_val()); - _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Alty); + if constexpr (!conjunction_v, _Uses_default_destroy<_Rebound, _Item*>>) { + _Reverse_destroy_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, this->_Get_val()); } } @@ -2247,7 +2235,7 @@ _NODISCARD allocate_shared(const _Alloc& _Al, _Types&&... _Args) { // make a shared_ptr to non-array object // Note: As of 2019-05-28, this implements the proposed resolution of LWG-3210 (which controls whether // allocator::construct sees T or const T when _Ty is const qualified) - using _Refoa = _Ref_count_obj_alloc2, _Alloc>; + using _Refoa = _Ref_count_obj_alloc3, _Alloc>; using _Alblock = _Rebind_alloc_t<_Alloc, _Refoa>; _Alblock _Rebound(_Al); _Alloc_construct_ptr<_Alblock> _Constructor{_Rebound}; From 731ab4878a54d90d81efcb987807b54fd973d1f6 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 6 Apr 2020 18:25:58 -0700 Subject: [PATCH 48/52] Improve comments. --- stl/inc/memory | 13 +++++++++---- .../tests/P0674R1_make_shared_for_arrays/test.cpp | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index 5750de3d7b6..e15bfd6e5fb 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1809,9 +1809,10 @@ template class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in control block, no allocator public: - _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} + _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} // value-initializing _Storage is necessary here - explicit _Ref_count_bounded_array(const remove_extent_t<_Ty>& _Val) : _Ref_count_base() { + explicit _Ref_count_bounded_array(const remove_extent_t<_Ty>& _Val) + : _Ref_count_base() { // don't value-initialize _Storage _Uninitialized_fill_multidimensional_n(_Storage._Value, extent_v<_Ty>, _Val); } @@ -2118,12 +2119,13 @@ private: using _Rebound = _Rebind_alloc_t<_Alloc, _Item>; public: - explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { + explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg) + : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { // don't value-initialize _Storage _Uninitialized_value_construct_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, this->_Get_val()); } explicit _Ref_count_bounded_array_alloc(const _Alloc& _Al_arg, const remove_extent_t<_Ty>& _Val) - : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { + : _Ebco_base<_Rebound>(_Al_arg), _Ref_count_base() { // don't value-initialize _Storage _Uninitialized_fill_multidimensional_n_al(_Storage._Value, extent_v<_Ty>, _Val, this->_Get_val()); } @@ -2172,6 +2174,9 @@ struct _Global_delete_guard { void* _Target; ~_Global_delete_guard() { + // While this branch is technically unnecessary because N4849 [new.delete.single]/17 requires + // `::operator delete(nullptr)` to be a no-op, it's here to help optimizers see that after + // `_Guard._Target = nullptr;`, this destructor can be eliminated. if (_Target) { ::operator delete(_Target); } diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 9651eb757e6..c895d3a283f 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -21,7 +21,7 @@ struct ReportAddress; vector ascendingAddressBuffer; vector descendingAddressBuffer; -// According to N4849, the default behaviour of new[](size) is to return +// According to N4849, the default behavior of new[](size) is to return // new(size), so only the latter needs to be redefined. void* operator new(size_t size) { void* const p = ::operator new(size, nothrow); From d017e0ae884f2d0e6d3aac9324104206fd712a8f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 6 Apr 2020 18:41:12 -0700 Subject: [PATCH 49/52] Brace all control flow. --- .../P0674R1_make_shared_for_arrays/test.cpp | 90 ++++++++++++------- 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index c895d3a283f..fe781448f3e 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -73,15 +73,17 @@ struct ReportAddress { }; void assert_ascending_init() { - for (unsigned i = 1; i < ascendingAddressBuffer.size(); ++i) + for (unsigned i = 1; i < ascendingAddressBuffer.size(); ++i) { assert(ascendingAddressBuffer[i - 1] < ascendingAddressBuffer[i]); + } ascendingAddressBuffer.clear(); } void assert_descending_destruct() { - for (unsigned i = 1; i < descendingAddressBuffer.size(); ++i) + for (unsigned i = 1; i < descendingAddressBuffer.size(); ++i) { assert(descendingAddressBuffer[i - 1] > descendingAddressBuffer[i]); + } descendingAddressBuffer.clear(); } @@ -142,14 +144,18 @@ void test_make_shared_not_array() { void test_make_shared_array_known_bounds() { shared_ptr p0 = make_shared(); - for (int i = 0; i < 100; ++i) + for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); + } shared_ptr p1 = make_shared_assert(); - for (int i = 0; i < 2; ++i) - for (int j = 0; j < 8; ++j) - for (int k = 0; k < 9; ++k) + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 8; ++j) { + for (int k = 0; k < 9; ++k) { assert(p1[i][j][k].value == 106); + } + } + } shared_ptr p2 = make_shared({"Meow!", "Purr"}); for (int i = 0; i < 10; ++i) { @@ -158,13 +164,16 @@ void test_make_shared_array_known_bounds() { } shared_ptr[3]> p3 = make_shared[3]>({9, 9, 9}); - for (int i = 0; i < 3; ++i) - for (int& val : p3[i]) + for (int i = 0; i < 3; ++i) { + for (int& val : p3[i]) { assert(val == 9); + } + } shared_ptr p4 = make_shared_init_assert({2, 8, 9}); - for (int i = 0; i < 5; ++i) + for (int i = 0; i < 5; ++i) { assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + } test_make_init_destruct_order(); // success one dimensional @@ -177,14 +186,18 @@ void test_make_shared_array_known_bounds() { void test_make_shared_array_unknown_bounds() { shared_ptr p0 = make_shared(100); - for (int i = 0; i < 100; ++i) + for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); + } shared_ptr p1 = make_shared_assert(2u); - for (int i = 0; i < 2; ++i) - for (int j = 0; j < 8; ++j) - for (int k = 0; k < 9; ++k) + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 8; ++j) { + for (int k = 0; k < 9; ++k) { assert(p1[i][j][k].value == 106); + } + } + } shared_ptr p2 = make_shared(10, {"Meow!", "Purr"}); for (int i = 0; i < 10; ++i) { @@ -193,13 +206,16 @@ void test_make_shared_array_unknown_bounds() { } shared_ptr[]> p3 = make_shared[]>(3, {9, 9, 9}); - for (int i = 0; i < 3; ++i) - for (int& val : p3[i]) + for (int i = 0; i < 3; ++i) { + for (int& val : p3[i]) { assert(val == 9); + } + } shared_ptr p4 = make_shared_init_assert(5, {2, 8, 9}); - for (int i = 0; i < 5; ++i) + for (int i = 0; i < 5; ++i) { assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + } shared_ptr p5 = make_shared_assert(0u); // p5 cannot be dereferenced @@ -329,18 +345,22 @@ void test_allocate_shared_array_known_bounds() { CustomAlloc a0{}; { shared_ptr p0 = allocate_shared(a0); - for (int i = 0; i < 100; ++i) + for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); + } } assert_construct_destruct_equal(); CustomAlloc a1{}; { shared_ptr p1 = allocate_shared_assert(144, a1); - for (int i = 0; i < 2; ++i) - for (int j = 0; j < 8; ++j) - for (int k = 0; k < 9; ++k) + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 8; ++j) { + for (int k = 0; k < 9; ++k) { assert(p1[i][j][k].value == 106); + } + } + } } assert_construct_destruct_equal(); @@ -357,17 +377,20 @@ void test_allocate_shared_array_known_bounds() { CustomAlloc> a3{}; { shared_ptr[3]> p3 = allocate_shared[3]>(a3, {9, 9, 9}); - for (int i = 0; i < 3; ++i) - for (int& val : p3[i]) + for (int i = 0; i < 3; ++i) { + for (int& val : p3[i]) { assert(val == 9); + } + } } assert_construct_destruct_equal(); CustomAlloc a4{}; { shared_ptr p4 = allocate_shared_init_assert(5, a4, {2, 8, 9}); - for (int i = 0; i < 5; ++i) + for (int i = 0; i < 5; ++i) { assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + } } assert_construct_destruct_equal(); @@ -384,18 +407,22 @@ void test_allocate_shared_array_unknown_bounds() { CustomAlloc a0{}; { shared_ptr p0 = allocate_shared(a0, 100); - for (int i = 0; i < 100; ++i) + for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); + } } assert_construct_destruct_equal(); CustomAlloc a1{}; { shared_ptr p1 = allocate_shared_assert(144, a1, 2u); - for (int i = 0; i < 2; ++i) - for (int j = 0; j < 8; ++j) - for (int k = 0; k < 9; ++k) + for (int i = 0; i < 2; ++i) { + for (int j = 0; j < 8; ++j) { + for (int k = 0; k < 9; ++k) { assert(p1[i][j][k].value == 106); + } + } + } } assert_construct_destruct_equal(); @@ -411,17 +438,20 @@ void test_allocate_shared_array_unknown_bounds() { CustomAlloc> a3{}; { shared_ptr[]> p3 = allocate_shared[]>(a3, 3, {9, 9, 9}); - for (int i = 0; i < 3; ++i) - for (int& val : p3[i]) + for (int i = 0; i < 3; ++i) { + for (int& val : p3[i]) { assert(val == 9); + } + } } assert_construct_destruct_equal(); CustomAlloc a4{}; { shared_ptr p4 = allocate_shared_init_assert(5, a4, 5, {2, 8, 9}); - for (int i = 0; i < 5; ++i) + for (int i = 0; i < 5; ++i) { assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); + } } assert_construct_destruct_equal(); From 5b4eb44574ae2ef280675b7263a7dfa5b0522932 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 6 Apr 2020 19:28:21 -0700 Subject: [PATCH 50/52] More test improvements. * Include for malloc. * Include for bad_alloc. * Include , newly used. * The precise Word Of Power is that `operator new` is "replaced". * Use size_t for vector indices; this respects 64-bit (not that these vectors can be large). Additionally, we conventionally never say `unsigned` - we would say `unsigned int`. * Remove artificial scopes around try/catch - they already introduce scopes, so this was just extra indentation. * Instead of constructing a std::string in a catch block, compare against a string_view literal, avoiding dynamic memory allocation. * Conventionally use preincrement. --- .../P0674R1_make_shared_for_arrays/test.cpp | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index fe781448f3e..8e5c45e8aa6 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -2,9 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include +#include #include #include +#include #include #include #include @@ -22,7 +25,7 @@ vector ascendingAddressBuffer; vector descendingAddressBuffer; // According to N4849, the default behavior of new[](size) is to return -// new(size), so only the latter needs to be redefined. +// new(size), so only the latter needs to be replaced. void* operator new(size_t size) { void* const p = ::operator new(size, nothrow); @@ -73,7 +76,7 @@ struct ReportAddress { }; void assert_ascending_init() { - for (unsigned i = 1; i < ascendingAddressBuffer.size(); ++i) { + for (size_t i = 1; i < ascendingAddressBuffer.size(); ++i) { assert(ascendingAddressBuffer[i - 1] < ascendingAddressBuffer[i]); } @@ -81,7 +84,7 @@ void assert_ascending_init() { } void assert_descending_destruct() { - for (unsigned i = 1; i < descendingAddressBuffer.size(); ++i) { + for (size_t i = 1; i < descendingAddressBuffer.size(); ++i) { assert(descendingAddressBuffer[i - 1] > descendingAddressBuffer[i]); } @@ -115,15 +118,13 @@ shared_ptr make_shared_init_assert(size_t size, const remove_extent_t& val template void test_make_init_destruct_order(Args&&... vals) { - { - try { - shared_ptr sp = make_shared(forward(vals)...); - assert_shared_use_get(sp); - } catch (const runtime_error& exc) { - string err = "Can't create more ReportAddress objects."; - assert(err.compare(exc.what()) == 0); - } + try { + shared_ptr sp = make_shared(forward(vals)...); + assert_shared_use_get(sp); + } catch (const runtime_error& exc) { + assert(exc.what() == "Can't create more ReportAddress objects."sv); } + assert_ascending_init(); assert_descending_destruct(); } @@ -258,7 +259,7 @@ struct ConstructConstrainingAllocator { allocator a; static_assert(is_same_v && is_same_v, "incorrect construct call"); allocator_traits>::construct(a, p, forward(vals)...); - constructCount++; + ++constructCount; } template @@ -266,7 +267,7 @@ struct ConstructConstrainingAllocator { allocator a; static_assert(is_same_v && is_same_v, "incorrect destroy call"); allocator_traits>::destroy(a, p); - destroyCount++; + ++destroyCount; } }; @@ -297,15 +298,14 @@ shared_ptr allocate_shared_init_assert(int elemCount, const A& a, size_t size template void test_allocate_init_destruct_order(Args&&... vals) { CustomAlloc> a{}; - { - try { - shared_ptr sp = allocate_shared(a, forward(vals)...); - assert_shared_use_get(sp); - } catch (const runtime_error& exc) { - string err = "Can't create more ReportAddress objects."; - assert(err.compare(exc.what()) == 0); - } + + try { + shared_ptr sp = allocate_shared(a, forward(vals)...); + assert_shared_use_get(sp); + } catch (const runtime_error& exc) { + assert(exc.what() == "Can't create more ReportAddress objects."sv); } + assert_construct_destruct_equal(); assert_ascending_init(); assert_descending_destruct(); From 0c0cb15c0a059c9a39dbeba704884abb7268a34b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 6 Apr 2020 21:08:07 -0700 Subject: [PATCH 51/52] Final test improvements. * Initialize InitialValue::value instead of reassigning it. * Test `canCreate > 0` instead of directly testing an integer for being nonzero. * assert_shared_use_get() is an observer. * Always use template argument deduction when calling assert_shared_use_get(). * Add many missing calls to assert_shared_use_get(). * Test plain int (and arrays of known/unknown bound) as it's sensitive to the difference between default-init and value-init. The other types tested have constructors. * Iterating through vectors with `int&` was correct, but `const auto&` is more conventional in our tests for pure observation. (This is more important for maps, where getting the element type wrong is a real possibility.) --- .../P0674R1_make_shared_for_arrays/test.cpp | 95 ++++++++++++++++--- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 8e5c45e8aa6..57e17d135e8 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -48,9 +48,7 @@ struct InitialValue { InitialValue() {} - InitialValue(int a, int b) { - value = a + b; - } + InitialValue(int a, int b) : value(a + b) {} }; struct ThreeIntWrap { @@ -61,7 +59,7 @@ struct ThreeIntWrap { struct ReportAddress { ReportAddress() { - if (canCreate) { + if (canCreate > 0) { ascendingAddressBuffer.push_back(this); --canCreate; } else { @@ -92,7 +90,7 @@ void assert_descending_destruct() { } template -void assert_shared_use_get(shared_ptr& sp) { +void assert_shared_use_get(const shared_ptr& sp) { assert(sp.use_count() == 1); assert(sp.get() != nullptr); } @@ -101,7 +99,7 @@ template shared_ptr make_shared_assert(Args&&... vals) { int count = allocationCount; shared_ptr sp = make_shared(forward(vals)...); - assert_shared_use_get(sp); + assert_shared_use_get(sp); assert(count + 1 == allocationCount); return sp; } @@ -131,20 +129,27 @@ void test_make_init_destruct_order(Args&&... vals) { void test_make_shared_not_array() { shared_ptr> p0 = make_shared>(); + assert_shared_use_get(p0); assert(p0->empty()); shared_ptr p1 = make_shared_assert(); assert(p1->value == 106); shared_ptr p2 = make_shared("Meow!", 2u, 3u); + assert_shared_use_get(p2); assert(p2->compare("ow!") == 0); shared_ptr p3 = make_shared_assert(40, 2); assert(p3->value == 42); + + shared_ptr p4 = make_shared(); + assert_shared_use_get(p4); + assert(*p4 == 0); } void test_make_shared_array_known_bounds() { shared_ptr p0 = make_shared(); + assert_shared_use_get(p0); for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); } @@ -159,14 +164,16 @@ void test_make_shared_array_known_bounds() { } shared_ptr p2 = make_shared({"Meow!", "Purr"}); + assert_shared_use_get(p2); for (int i = 0; i < 10; ++i) { assert(p2[i][0].compare("Meow!") == 0); assert(p2[i][1].compare("Purr") == 0); } shared_ptr[3]> p3 = make_shared[3]>({9, 9, 9}); + assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { - for (int& val : p3[i]) { + for (const auto& val : p3[i]) { assert(val == 9); } } @@ -176,6 +183,16 @@ void test_make_shared_array_known_bounds() { assert(p4[i].v1 == 2 && p4[i].v2 == 8 && p4[i].v3 == 9); } + shared_ptr p5 = make_shared(); + assert_shared_use_get(p5); + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 2; ++j) { + for (int k = 0; k < 9; ++k) { + assert(p5[0][i][j][k] == 0); + } + } + } + test_make_init_destruct_order(); // success one dimensional test_make_init_destruct_order(); // failure one dimensional @@ -187,6 +204,7 @@ void test_make_shared_array_known_bounds() { void test_make_shared_array_unknown_bounds() { shared_ptr p0 = make_shared(100); + assert_shared_use_get(p0); for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); } @@ -201,14 +219,16 @@ void test_make_shared_array_unknown_bounds() { } shared_ptr p2 = make_shared(10, {"Meow!", "Purr"}); + assert_shared_use_get(p2); for (int i = 0; i < 10; ++i) { assert(p2[i][0].compare("Meow!") == 0); assert(p2[i][1].compare("Purr") == 0); } shared_ptr[]> p3 = make_shared[]>(3, {9, 9, 9}); + assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { - for (int& val : p3[i]) { + for (const auto& val : p3[i]) { assert(val == 9); } } @@ -220,6 +240,16 @@ void test_make_shared_array_unknown_bounds() { shared_ptr p5 = make_shared_assert(0u); // p5 cannot be dereferenced + shared_ptr p6 = make_shared(4u); + assert_shared_use_get(p6); + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 5; ++j) { + for (int k = 0; k < 6; ++k) { + assert(p6[i][j][k] == 0); + } + } + } + test_make_init_destruct_order(5u); // success one dimensional test_make_init_destruct_order(20u); // failure one dimensional @@ -315,7 +345,7 @@ void test_allocate_shared_not_array() { CustomAlloc> a0{}; { shared_ptr> p0 = allocate_shared>(a0); - assert_shared_use_get>(p0); + assert_shared_use_get(p0); assert(p0->empty()); } assert_construct_destruct_equal(); @@ -330,6 +360,7 @@ void test_allocate_shared_not_array() { CustomAlloc a2{}; { shared_ptr p2 = allocate_shared(a2, "Meow!", 2u, 3u); + assert_shared_use_get(p2); assert(p2->compare("ow!") == 0); } assert_construct_destruct_equal(); @@ -339,12 +370,21 @@ void test_allocate_shared_not_array() { assert(p3->value == 42); } assert_construct_destruct_equal(); + + CustomAlloc a4{}; + { + shared_ptr p4 = allocate_shared(a4); + assert_shared_use_get(p4); + assert(*p4 == 0); + } + assert_construct_destruct_equal(); } void test_allocate_shared_array_known_bounds() { CustomAlloc a0{}; { shared_ptr p0 = allocate_shared(a0); + assert_shared_use_get(p0); for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); } @@ -366,6 +406,7 @@ void test_allocate_shared_array_known_bounds() { { shared_ptr p2 = allocate_shared(a0, {"Meow!", "Purr"}); + assert_shared_use_get(p2); for (int i = 0; i < 10; ++i) { assert(p2[i][0].compare("Meow!") == 0); assert(p2[i][1].compare("Purr") == 0); @@ -373,12 +414,12 @@ void test_allocate_shared_array_known_bounds() { } assert_construct_destruct_equal(); - CustomAlloc> a3{}; { shared_ptr[3]> p3 = allocate_shared[3]>(a3, {9, 9, 9}); + assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { - for (int& val : p3[i]) { + for (const auto& val : p3[i]) { assert(val == 9); } } @@ -394,6 +435,20 @@ void test_allocate_shared_array_known_bounds() { } assert_construct_destruct_equal(); + CustomAlloc a5{}; + { + shared_ptr p5 = allocate_shared(a5); + assert_shared_use_get(p5); + for (int i = 0; i < 7; ++i) { + for (int j = 0; j < 2; ++j) { + for (int k = 0; k < 9; ++k) { + assert(p5[0][i][j][k] == 0); + } + } + } + } + assert_construct_destruct_equal(); + test_allocate_init_destruct_order(); // success one dimensional test_allocate_init_destruct_order(); // failure one dimensional @@ -407,6 +462,7 @@ void test_allocate_shared_array_unknown_bounds() { CustomAlloc a0{}; { shared_ptr p0 = allocate_shared(a0, 100); + assert_shared_use_get(p0); for (int i = 0; i < 100; ++i) { assert(p0[i].empty()); } @@ -428,6 +484,7 @@ void test_allocate_shared_array_unknown_bounds() { { shared_ptr p2 = allocate_shared(a0, 10, {"Meow!", "Purr"}); + assert_shared_use_get(p2); for (int i = 0; i < 10; ++i) { assert(p2[i][0].compare("Meow!") == 0); assert(p2[i][1].compare("Purr") == 0); @@ -438,8 +495,9 @@ void test_allocate_shared_array_unknown_bounds() { CustomAlloc> a3{}; { shared_ptr[]> p3 = allocate_shared[]>(a3, 3, {9, 9, 9}); + assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { - for (int& val : p3[i]) { + for (const auto& val : p3[i]) { assert(val == 9); } } @@ -459,6 +517,19 @@ void test_allocate_shared_array_unknown_bounds() { { shared_ptr p5 = allocate_shared_assert(0, a5, 0u); } // p5 cannot be dereferenced assert_construct_destruct_equal(); + { + shared_ptr p6 = allocate_shared(a5, 4u); + assert_shared_use_get(p6); + for (int i = 0; i < 4; ++i) { + for (int j = 0; j < 5; ++j) { + for (int k = 0; k < 6; ++k) { + assert(p6[i][j][k] == 0); + } + } + } + } + assert_construct_destruct_equal(); + test_allocate_init_destruct_order(5u); // success one dimensional test_allocate_init_destruct_order(20u); // failure one dimensional From e7daab40d85c202d709c21f522ec54d58ad32029 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 7 Apr 2020 18:41:52 -0700 Subject: [PATCH 52/52] More code review feedback. * Reorder friendship to match the Standard's declaration order. * Extract `_Element_size` for simplicity. * Support extended alignment in `_Allocate_flexible_array`. * Add `_Deallocate_flexible_array` to handle extended alignment. * Mark guard constructors as TRANSITION, P1771R1. * Handle non-pointer iterators when calling `destroy_at()`. * Add `static_assert` to array control blocks. * Add `HighlyAligned` test coverage. * Other test improvements. --- stl/inc/memory | 79 ++++++++++++------- .../P0674R1_make_shared_for_arrays/test.cpp | 68 +++++++++++++++- tests/tr1/test.lst | 5 +- 3 files changed, 121 insertions(+), 31 deletions(-) diff --git a/stl/inc/memory b/stl/inc/memory index e15bfd6e5fb..f8c567ef3d3 100644 --- a/stl/inc/memory +++ b/stl/inc/memory @@ -1273,32 +1273,32 @@ private: template friend enable_if_t, shared_ptr<_Ty0>> make_shared(_Types&&... _Args); + template + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); + template friend enable_if_t, shared_ptr<_Ty0>> make_shared(size_t _Count); - template - friend enable_if_t, shared_ptr<_Ty0>> make_shared( - size_t _Count, const remove_extent_t<_Ty0>& _Val); + template + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( + const _Alloc& _Al_arg, size_t _Count); template friend enable_if_t, shared_ptr<_Ty0>> make_shared(); - template - friend enable_if_t, shared_ptr<_Ty0>> make_shared(const remove_extent_t<_Ty0>& _Val); - - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg, _Types&&... _Args); - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( - const _Alloc& _Al_arg, size_t _Count); + friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg); + + template + friend enable_if_t, shared_ptr<_Ty0>> make_shared( + size_t _Count, const remove_extent_t<_Ty0>& _Val); template friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( const _Alloc& _Al_arg, size_t _Count, const remove_extent_t<_Ty0>& _Val); - template - friend enable_if_t, shared_ptr<_Ty0>> allocate_shared(const _Alloc& _Al_arg); + template + friend enable_if_t, shared_ptr<_Ty0>> make_shared(const remove_extent_t<_Ty0>& _Val); template friend enable_if_t, shared_ptr<_Ty0>> allocate_shared( @@ -1577,18 +1577,18 @@ _NODISCARD size_t _Calculate_bytes_for_flexible_array(const size_t _Count) noexc size_t _Bytes = sizeof(_Refc); // contains storage for one element if (_Count > 1) { - using _Element_type = typename _Refc::_Element_type; + constexpr size_t _Element_size = sizeof(typename _Refc::_Element_type); size_t _Extra_bytes; if constexpr (_Check == _Check_overflow::_Yes) { - _Extra_bytes = _Get_size_of_n(_Count - 1); // check multiplication overflow + _Extra_bytes = _Get_size_of_n<_Element_size>(_Count - 1); // check multiplication overflow if (_Extra_bytes > static_cast(-1) - _Bytes - (_Align - 1)) { // assume worst case adjustment _Throw_bad_array_new_length(); // addition overflow } } else { - _Extra_bytes = sizeof(_Element_type) * (_Count - 1); + _Extra_bytes = _Element_size * (_Count - 1); } _Bytes += _Extra_bytes; @@ -1606,8 +1606,23 @@ _NODISCARD size_t _Calculate_bytes_for_flexible_array(const size_t _Count) noexc template _NODISCARD _Refc* _Allocate_flexible_array(const size_t _Count) { - const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); - return static_cast<_Refc*>(::operator new(_Bytes)); + const size_t _Bytes = _Calculate_bytes_for_flexible_array<_Refc, _Check_overflow::_Yes>(_Count); + constexpr size_t _Align = alignof(_Refc); + if constexpr (_Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) { + return static_cast<_Refc*>(::operator new(_Bytes)); + } else { + return static_cast<_Refc*>(::operator new (_Bytes, align_val_t{_Align})); + } +} + +template +void _Deallocate_flexible_array(_Refc* const _Ptr) noexcept { + constexpr size_t _Align = alignof(_Refc); + if constexpr (_Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__) { + ::operator delete(static_cast(_Ptr)); + } else { + ::operator delete (static_cast(_Ptr), align_val_t{_Align}); + } } template @@ -1616,7 +1631,8 @@ struct _Uninitialized_rev_destroying_backout { _NoThrowIt _First; _NoThrowIt _Last; - explicit _Uninitialized_rev_destroying_backout(_NoThrowIt _Dest) noexcept : _First(_Dest), _Last(_Dest) {} + explicit _Uninitialized_rev_destroying_backout(_NoThrowIt _Dest) noexcept + : _First(_Dest), _Last(_Dest) {} // TRANSITION, P1771R1 [[nodiscard]] For Constructors _Uninitialized_rev_destroying_backout(const _Uninitialized_rev_destroying_backout&) = delete; _Uninitialized_rev_destroying_backout& operator=(const _Uninitialized_rev_destroying_backout&) = delete; @@ -1624,7 +1640,7 @@ struct _Uninitialized_rev_destroying_backout { ~_Uninitialized_rev_destroying_backout() { while (_Last != _First) { --_Last; - _STD destroy_at(_Last); + _STD destroy_at(_STD addressof(*_Last)); } } @@ -1727,6 +1743,8 @@ template >> class _Ref_count_unbounded_array : public _Ref_count_base { // handle reference counting for unbounded array with trivial destruction in control block, no allocator public: + static_assert(is_unbounded_array_v<_Ty>); + using _Element_type = remove_extent_t<_Ty>; explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base() { @@ -1758,7 +1776,7 @@ private: virtual void _Delete_this() noexcept override { // destroy self this->~_Ref_count_unbounded_array(); - ::operator delete(static_cast(this)); + _Deallocate_flexible_array(this); } }; @@ -1766,6 +1784,8 @@ template class _Ref_count_unbounded_array<_Ty, false> : public _Ref_count_base { // handle reference counting for unbounded array with non-trivial destruction in control block, no allocator public: + static_assert(is_unbounded_array_v<_Ty>); + using _Element_type = remove_extent_t<_Ty>; explicit _Ref_count_unbounded_array(const size_t _Count) : _Ref_count_base(), _Size(_Count) { @@ -1800,7 +1820,7 @@ private: virtual void _Delete_this() noexcept override { // destroy self this->~_Ref_count_unbounded_array(); - ::operator delete(static_cast(this)); + _Deallocate_flexible_array(this); } }; @@ -1809,6 +1829,8 @@ template class _Ref_count_bounded_array : public _Ref_count_base { // handle reference counting for bounded array in control block, no allocator public: + static_assert(is_bounded_array_v<_Ty>); + _Ref_count_bounded_array() : _Ref_count_base(), _Storage() {} // value-initializing _Storage is necessary here explicit _Ref_count_bounded_array(const remove_extent_t<_Ty>& _Val) @@ -1927,7 +1949,7 @@ private: public: _Uninitialized_rev_destroying_backout_al(pointer _Dest, _Alloc& _Al_) noexcept - : _First(_Dest), _Last(_Dest), _Al(_Al_) {} + : _First(_Dest), _Last(_Dest), _Al(_Al_) {} // TRANSITION, P1771R1 [[nodiscard]] For Constructors _Uninitialized_rev_destroying_backout_al(const _Uninitialized_rev_destroying_backout_al&) = delete; _Uninitialized_rev_destroying_backout_al& operator=(const _Uninitialized_rev_destroying_backout_al&) = delete; @@ -2050,6 +2072,7 @@ class __declspec(empty_bases) _Ref_count_unbounded_array_alloc public _Ref_count_base { // handle reference counting for unbounded array in control block, allocator private: + static_assert(is_unbounded_array_v<_Ty>); static_assert(is_same_v<_Ty, remove_cv_t<_Ty>>, "allocate_shared should remove_cv_t"); using _Item = remove_all_extents_t<_Ty>; @@ -2113,6 +2136,7 @@ class __declspec(empty_bases) _Ref_count_bounded_array_alloc public _Ref_count_base { // handle reference counting for bounded array in control block, allocator private: + static_assert(is_bounded_array_v<_Ty>); static_assert(is_same_v<_Ty, remove_cv_t<_Ty>>, "allocate_shared should remove_cv_t"); using _Item = remove_all_extents_t<_Ty>; @@ -2170,15 +2194,16 @@ _NODISCARD } #if _HAS_CXX20 +template struct _Global_delete_guard { - void* _Target; + _Refc* _Target; ~_Global_delete_guard() { // While this branch is technically unnecessary because N4849 [new.delete.single]/17 requires // `::operator delete(nullptr)` to be a no-op, it's here to help optimizers see that after // `_Guard._Target = nullptr;`, this destructor can be eliminated. if (_Target) { - ::operator delete(_Target); + _Deallocate_flexible_array(_Target); } } }; @@ -2188,7 +2213,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared(c // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; const auto _Rx = _Allocate_flexible_array<_Refc>(_Count); - _Global_delete_guard _Guard{_Rx}; + _Global_delete_guard<_Refc> _Guard{_Rx}; ::new (static_cast(_Rx)) _Refc(_Count); _Guard._Target = nullptr; shared_ptr<_Ty> _Ret; @@ -2202,7 +2227,7 @@ _NODISCARD enable_if_t, shared_ptr<_Ty>> make_shared( // make a shared_ptr to an unbounded array using _Refc = _Ref_count_unbounded_array<_Ty>; const auto _Rx = _Allocate_flexible_array<_Refc>(_Count); - _Global_delete_guard _Guard{_Rx}; + _Global_delete_guard<_Refc> _Guard{_Rx}; ::new (static_cast(_Rx)) _Refc(_Count, _Val); _Guard._Target = nullptr; shared_ptr<_Ty> _Ret; diff --git a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp index 57e17d135e8..3a3304571c7 100644 --- a/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp +++ b/tests/std/tests/P0674R1_make_shared_for_arrays/test.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #include +#include #include #include #include @@ -24,8 +25,8 @@ struct ReportAddress; vector ascendingAddressBuffer; vector descendingAddressBuffer; -// According to N4849, the default behavior of new[](size) is to return -// new(size), so only the latter needs to be replaced. +// According to N4849, the default behavior of operator new[](size) is to return +// operator new(size), so only the latter needs to be replaced. void* operator new(size_t size) { void* const p = ::operator new(size, nothrow); @@ -46,7 +47,7 @@ void* operator new(size_t size, const nothrow_t&) noexcept { struct InitialValue { int value = 106; - InitialValue() {} + InitialValue() = default; InitialValue(int a, int b) : value(a + b) {} }; @@ -57,6 +58,13 @@ struct ThreeIntWrap { int v3; }; +struct alignas(32) HighlyAligned { + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +}; + struct ReportAddress { ReportAddress() { if (canCreate > 0) { @@ -145,6 +153,11 @@ void test_make_shared_not_array() { shared_ptr p4 = make_shared(); assert_shared_use_get(p4); assert(*p4 == 0); + + shared_ptr p5 = make_shared(); + assert_shared_use_get(p5); + assert(reinterpret_cast(p5.get()) % alignof(HighlyAligned) == 0); + assert(p5->a == 0 && p5->b == 0 && p5->c == 0 && p5->d == 0); } void test_make_shared_array_known_bounds() { @@ -173,6 +186,7 @@ void test_make_shared_array_known_bounds() { shared_ptr[3]> p3 = make_shared[3]>({9, 9, 9}); assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { + assert(p3[i].size() == 3); for (const auto& val : p3[i]) { assert(val == 9); } @@ -193,6 +207,13 @@ void test_make_shared_array_known_bounds() { } } + shared_ptr p6 = make_shared(); + assert_shared_use_get(p6); + assert(reinterpret_cast(p6.get()) % alignof(HighlyAligned) == 0); + for (int i = 0; i < 6; ++i) { + assert(p6[i].a == 0 && p6[i].b == 0 && p6[i].c == 0 && p6[i].d == 0); + } + test_make_init_destruct_order(); // success one dimensional test_make_init_destruct_order(); // failure one dimensional @@ -228,6 +249,7 @@ void test_make_shared_array_unknown_bounds() { shared_ptr[]> p3 = make_shared[]>(3, {9, 9, 9}); assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { + assert(p3[i].size() == 3); for (const auto& val : p3[i]) { assert(val == 9); } @@ -250,6 +272,13 @@ void test_make_shared_array_unknown_bounds() { } } + shared_ptr p7 = make_shared(7u); + assert_shared_use_get(p7); + assert(reinterpret_cast(p7.get()) % alignof(HighlyAligned) == 0); + for (int i = 0; i < 7; ++i) { + assert(p7[i].a == 0 && p7[i].b == 0 && p7[i].c == 0 && p7[i].d == 0); + } + test_make_init_destruct_order(5u); // success one dimensional test_make_init_destruct_order(20u); // failure one dimensional @@ -378,6 +407,15 @@ void test_allocate_shared_not_array() { assert(*p4 == 0); } assert_construct_destruct_equal(); + + CustomAlloc a5{}; + { + shared_ptr p5 = allocate_shared(a5); + assert_shared_use_get(p5); + assert(reinterpret_cast(p5.get()) % alignof(HighlyAligned) == 0); + assert(p5->a == 0 && p5->b == 0 && p5->c == 0 && p5->d == 0); + } + assert_construct_destruct_equal(); } void test_allocate_shared_array_known_bounds() { @@ -419,6 +457,7 @@ void test_allocate_shared_array_known_bounds() { shared_ptr[3]> p3 = allocate_shared[3]>(a3, {9, 9, 9}); assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { + assert(p3[i].size() == 3); for (const auto& val : p3[i]) { assert(val == 9); } @@ -449,6 +488,17 @@ void test_allocate_shared_array_known_bounds() { } assert_construct_destruct_equal(); + CustomAlloc a6{}; + { + shared_ptr p6 = allocate_shared(a6); + assert_shared_use_get(p6); + assert(reinterpret_cast(p6.get()) % alignof(HighlyAligned) == 0); + for (int i = 0; i < 6; ++i) { + assert(p6[i].a == 0 && p6[i].b == 0 && p6[i].c == 0 && p6[i].d == 0); + } + } + assert_construct_destruct_equal(); + test_allocate_init_destruct_order(); // success one dimensional test_allocate_init_destruct_order(); // failure one dimensional @@ -497,6 +547,7 @@ void test_allocate_shared_array_unknown_bounds() { shared_ptr[]> p3 = allocate_shared[]>(a3, 3, {9, 9, 9}); assert_shared_use_get(p3); for (int i = 0; i < 3; ++i) { + assert(p3[i].size() == 3); for (const auto& val : p3[i]) { assert(val == 9); } @@ -530,6 +581,17 @@ void test_allocate_shared_array_unknown_bounds() { } assert_construct_destruct_equal(); + CustomAlloc a7{}; + { + shared_ptr p7 = allocate_shared(a7, 7u); + assert_shared_use_get(p7); + assert(reinterpret_cast(p7.get()) % alignof(HighlyAligned) == 0); + for (int i = 0; i < 7; ++i) { + assert(p7[i].a == 0 && p7[i].b == 0 && p7[i].c == 0 && p7[i].d == 0); + } + } + assert_construct_destruct_equal(); + test_allocate_init_destruct_order(5u); // success one dimensional test_allocate_init_destruct_order(20u); // failure one dimensional diff --git a/tests/tr1/test.lst b/tests/tr1/test.lst index 27319a45473..e97d6e55731 100644 --- a/tests/tr1/test.lst +++ b/tests/tr1/test.lst @@ -179,7 +179,10 @@ tests\string1 tests\string2 tests\strstream tests\system_error -tests\thread + +# TRANSITION, flaky test +# tests\thread + tests\tuple tests\type_traits1 tests\type_traits2