From 7bb4110d0bdb4bd68eb89a7d540bd1b82504301a Mon Sep 17 00:00:00 2001 From: Michael Schellenberger Costa Date: Tue, 23 Mar 2021 11:02:45 +0100 Subject: [PATCH] Cleanup construction of vector with known size --- stl/inc/vector | 135 +++++++++++++++++++------------------------------ 1 file changed, 51 insertions(+), 84 deletions(-) diff --git a/stl/inc/vector b/stl/inc/vector index 66cd02491d4..4a50511cdbf 100644 --- a/stl/inc/vector +++ b/stl/inc/vector @@ -481,114 +481,56 @@ public: _Mypair._Myval2._Alloc_proxy(_GET_PROXY_ALLOCATOR(_Alty, _Getal())); } -private: - template - _CONSTEXPR20_CONTAINER void _Construct_n_copies_of_ty(_CRT_GUARDOVERFLOW const size_type _Count, const _Ty2& _Val) { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - auto& _Al = _Getal(); - auto& _My_data = _Mypair._Myval2; - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); - if (_Count != 0) { - _Buy_nonzero(_Count); - _Tidy_guard _Guard{this}; - if constexpr (is_same_v<_Ty2, _Ty>) { - _My_data._Mylast = _Uninitialized_fill_n(_My_data._Myfirst, _Count, _Val, _Al); - } else { - _My_data._Mylast = _Uninitialized_value_construct_n(_My_data._Myfirst, _Count, _Al); - } - _Guard._Target = nullptr; - } - - _Proxy._Release(); - } - -public: _CONSTEXPR20_CONTAINER explicit vector(_CRT_GUARDOVERFLOW const size_type _Count, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Construct_n_copies_of_ty(_Count, _Value_init_tag{}); + _Construct_n(_Count); } _CONSTEXPR20_CONTAINER vector( _CRT_GUARDOVERFLOW const size_type _Count, const _Ty& _Val, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { - _Construct_n_copies_of_ty(_Count, _Val); - } - -private: - template - _CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, input_iterator_tag) { - _Tidy_guard _Guard{this}; - for (; _First != _Last; ++_First) { - emplace_back(*_First); // performance note: emplace_back()'s strong guarantee is unnecessary here - } - - _Guard._Target = nullptr; + _Construct_n(_Count, _Val); } - template - _CONSTEXPR20_CONTAINER void _Range_construct_or_tidy(_Iter _First, _Iter _Last, forward_iterator_tag) { - const auto _Count = _Convert_size(static_cast(_STD distance(_First, _Last))); - if (_Count != 0) { - _Buy_nonzero(_Count); - _Tidy_guard _Guard{this}; - auto& _My_data = _Mypair._Myval2; - _My_data._Mylast = _Uninitialized_copy(_First, _Last, _My_data._Myfirst, _Getal()); - _Guard._Target = nullptr; - } - } - -public: template , int> = 0> _CONSTEXPR20_CONTAINER vector(_Iter _First, _Iter _Last, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); _Adl_verify_range(_First, _Last); - _Range_construct_or_tidy(_Get_unwrapped(_First), _Get_unwrapped(_Last), _Iter_cat_t<_Iter>{}); - _Proxy._Release(); + auto _UFirst = _Get_unwrapped(_First); + auto _ULast = _Get_unwrapped(_Last); + if constexpr (is_same_v<_Iter_cat_t<_Iter>, input_iterator_tag>) { + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); + _Tidy_guard _Guard{this}; + + for (; _UFirst != _ULast; ++_UFirst) { + emplace_back(*_UFirst); // performance note: emplace_back()'s strong guarantee is unnecessary here + } + + _Guard._Target = nullptr; + _Proxy._Release(); + } else { + const auto _Count = _Convert_size(static_cast(_STD distance(_UFirst, _ULast))); + _Construct_n(_Count, _STD move(_UFirst), _STD move(_ULast)); + } } _CONSTEXPR20_CONTAINER vector(initializer_list<_Ty> _Ilist, const _Alloc& _Al = _Alloc()) : _Mypair(_One_then_variadic_args_t{}, _Al) { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _Mypair._Myval2); - _Range_construct_or_tidy(_Ilist.begin(), _Ilist.end(), random_access_iterator_tag{}); - _Proxy._Release(); + _Construct_n(_Ilist.size(), _Ilist.begin(), _Ilist.end()); } _CONSTEXPR20_CONTAINER vector(const vector& _Right) : _Mypair(_One_then_variadic_args_t{}, _Alty_traits::select_on_container_copy_construction(_Right._Getal())) { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - auto& _My_data = _Mypair._Myval2; - const auto& _Right_data = _Right._Mypair._Myval2; - const pointer _Rightfirst = _Right_data._Myfirst; - const pointer _Rightlast = _Right_data._Mylast; - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); - if (_Rightfirst != _Rightlast) { - _Buy_raw(static_cast(_Rightlast - _Rightfirst)); - _Tidy_guard _Guard{this}; - _My_data._Mylast = _Uninitialized_copy(_Rightfirst, _Rightlast, _My_data._Myfirst, _Getal()); - _Guard._Target = nullptr; - } - - _Proxy._Release(); + const auto& _Right_data = _Right._Mypair._Myval2; + const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); + _Construct_n(_Count, _Right_data._Myfirst, _Right_data._Mylast); } _CONSTEXPR20_CONTAINER vector(const vector& _Right, const _Alloc& _Al) : _Mypair(_One_then_variadic_args_t{}, _Al) { - auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Getal()); - auto& _My_data = _Mypair._Myval2; - const auto& _Right_data = _Right._Mypair._Myval2; - const pointer _Rightfirst = _Right_data._Myfirst; - const pointer _Rightlast = _Right_data._Mylast; - _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); - if (_Rightfirst != _Rightlast) { - _Buy_raw(static_cast(_Rightlast - _Rightfirst)); - _Tidy_guard _Guard{this}; - _My_data._Mylast = _Uninitialized_copy(_Rightfirst, _Rightlast, _My_data._Myfirst, _Getal()); - _Guard._Target = nullptr; - } - - _Proxy._Release(); + const auto& _Right_data = _Right._Mypair._Myval2; + const auto _Count = static_cast(_Right_data._Mylast - _Right_data._Myfirst); + _Construct_n(_Count, _Right_data._Myfirst, _Right_data._Mylast); } private: @@ -1771,6 +1713,31 @@ private: } } + template + _CONSTEXPR20_CONTAINER void _Construct_n(_CRT_GUARDOVERFLOW const size_type _Count, _Valty&&... _Val) { + auto& _Al = _Getal(); + auto&& _Alproxy = _GET_PROXY_ALLOCATOR(_Alty, _Al); + auto& _My_data = _Mypair._Myval2; + _Container_proxy_ptr<_Alty> _Proxy(_Alproxy, _My_data); + if (_Count != 0) { + _Buy_nonzero(_Count); + _Tidy_guard _Guard{this}; + if constexpr (sizeof...(_Val) == 0) { + _My_data._Mylast = _Uninitialized_value_construct_n(_My_data._Myfirst, _Count, _Al); + } else if constexpr (sizeof...(_Val) == 1) { + static_assert(is_same_v<_Valty..., const _Ty&>, "Wrong type passed to _Construct_n"); + _My_data._Mylast = _Uninitialized_fill_n(_My_data._Myfirst, _Count, _Val..., _Al); + } else if constexpr (sizeof...(_Val) == 2) { + _My_data._Mylast = _Uninitialized_copy(_STD forward<_Valty>(_Val)..., _My_data._Myfirst, _Al); + } else { + static_assert(_Always_false<_Ty>, "Should be unreachable"); + } + _Guard._Target = nullptr; + } + + _Proxy._Release(); + } + [[noreturn]] static void _Xlength() { _Xlength_error("vector too long"); }