diff options
author | Andrew Luo <andrewluotechnologies@outlook.com> | 2020-08-06 19:35:43 +0100 |
---|---|---|
committer | Jonathan Wakely <jwakely@redhat.com> | 2020-08-06 19:49:07 +0100 |
commit | 140cf935cd118f7208b7c3826a8b9d50936242f0 (patch) | |
tree | 65f67d2de44231a18d83ebdb1fffa3eff6602d86 /libstdc++-v3/include/bits/basic_string.tcc | |
parent | 4e39f563c0cd25401f689c2093cb8c13692156ef (diff) |
libstdc++: Implement P0966 std::string::reserve should not shrink
Remove ability for reserve(n) to reduce a string's capacity. Add a new
reserve() overload that makes a shrink-to-fit request, and make
shrink_to_fit() use that.
libstdc++-v3/ChangeLog:
2020-07-30 Andrew Luo <andrewluotechnologies@outlook.com>
Jonathan Wakely <jwakely@redhat.com>
* config/abi/pre/gnu.ver (GLIBCXX_3.4): Use less greedy
patterns for basic_string members.
(GLIBCXX_3.4.29): Export new basic_string::reserve symbols.
* doc/xml/manual/status_cxx2020.xml: Update P0966 status.
* include/bits/basic_string.h (shrink_to_fit()): Call reserve().
(reserve(size_type)): Remove default argument.
(reserve()): Declare new overload.
[!_GLIBCXX_USE_CXX11_ABI] (shrink_to_fit, reserve): Likewise.
* include/bits/basic_string.tcc (reserve(size_type)): Remove
support for shrinking capacity.
(reserve()): Perform shrink-to-fit operation.
[!_GLIBCXX_USE_CXX11_ABI] (reserve): Likewise.
* testsuite/21_strings/basic_string/capacity/1.cc: Adjust to
reflect new behavior.
* testsuite/21_strings/basic_string/capacity/char/1.cc:
Likewise.
* testsuite/21_strings/basic_string/capacity/char/18654.cc:
Likewise.
* testsuite/21_strings/basic_string/capacity/char/2.cc:
Likewise.
* testsuite/21_strings/basic_string/capacity/wchar_t/1.cc:
Likewise.
* testsuite/21_strings/basic_string/capacity/wchar_t/18654.cc:
Likewise.
* testsuite/21_strings/basic_string/capacity/wchar_t/2.cc:
Likewise.
Diffstat (limited to 'libstdc++-v3/include/bits/basic_string.tcc')
-rw-r--r-- | libstdc++-v3/include/bits/basic_string.tcc | 119 |
1 files changed, 86 insertions, 33 deletions
diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 75218a40610..a64b63a37fb 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -280,29 +280,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_string<_CharT, _Traits, _Alloc>:: reserve(size_type __res) { - // Make sure we don't shrink below the current size. - if (__res < length()) - __res = length(); - const size_type __capacity = capacity(); - if (__res != __capacity) - { - if (__res > __capacity - || __res > size_type(_S_local_capacity)) - { - pointer __tmp = _M_create(__res, __capacity); - this->_S_copy(__tmp, _M_data(), length() + 1); - _M_dispose(); - _M_data(__tmp); - _M_capacity(__res); - } - else if (!_M_is_local()) - { - this->_S_copy(_M_local_data(), _M_data(), length() + 1); - _M_destroy(__capacity); - _M_data(_M_local_data()); - } - } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2968. Inconsistencies between basic_string reserve and + // vector/unordered_map/unordered_set reserve functions + // P0966 reserve should not shrink + if (__res <= __capacity) + return; + + pointer __tmp = _M_create(__res, __capacity); + this->_S_copy(__tmp, _M_data(), length() + 1); + _M_dispose(); + _M_data(__tmp); + _M_capacity(__res); } template<typename _CharT, typename _Traits, typename _Alloc> @@ -345,6 +335,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _CharT, typename _Traits, typename _Alloc> void basic_string<_CharT, _Traits, _Alloc>:: + reserve() + { + if (_M_is_local()) + return; + + const size_type __length = length(); + const size_type __capacity = _M_allocated_capacity; + + if (__length <= size_type(_S_local_capacity)) + { + this->_S_copy(_M_local_data(), _M_data(), __length + 1); + _M_destroy(__capacity); + _M_data(_M_local_data()); + } +#if __cpp_exceptions + else if (__length < __capacity) + try + { + pointer __tmp + = _Alloc_traits::allocate(_M_get_allocator(), __length + 1); + this->_S_copy(__tmp, _M_data(), __length + 1); + _M_dispose(); + _M_data(__tmp); + _M_capacity(__length); + } + catch (const __cxxabiv1::__forced_unwind&) + { throw; } + catch (...) + { /* swallow the exception */ } +#endif + } + + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>:: resize(size_type __n, _CharT __c) { const size_type __size = this->size(); @@ -953,16 +978,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_string<_CharT, _Traits, _Alloc>:: reserve(size_type __res) { - if (__res != this->capacity() || _M_rep()->_M_is_shared()) - { - // Make sure we don't shrink below the current size - if (__res < this->size()) - __res = this->size(); - const allocator_type __a = get_allocator(); - _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size()); - _M_rep()->_M_dispose(__a); - _M_data(__tmp); - } + const size_type __capacity = capacity(); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2968. Inconsistencies between basic_string reserve and + // vector/unordered_map/unordered_set reserve functions + // P0966 reserve should not shrink + if (__res <= __capacity) + { + if (!_M_rep()->_M_is_shared()) + return; + + // unshare, but keep same capacity + __res = __capacity; + } + + const allocator_type __a = get_allocator(); + _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size()); + _M_rep()->_M_dispose(__a); + _M_data(__tmp); } template<typename _CharT, typename _Traits, typename _Alloc> @@ -1006,7 +1040,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // The standard places no restriction on allocating more memory // than is strictly needed within this layer at the moment or as - // requested by an explicit application call to reserve(). + // requested by an explicit application call to reserve(n). // Many malloc implementations perform quite poorly when an // application attempts to allocate memory in a stepwise fashion @@ -1140,6 +1174,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this; } + template<typename _CharT, typename _Traits, typename _Alloc> + void + basic_string<_CharT, _Traits, _Alloc>:: + reserve() + { + if (length() < capacity() || _M_rep()->_M_is_shared()) + try + { + const allocator_type __a = get_allocator(); + _CharT* __tmp = _M_rep()->_M_clone(__a); + _M_rep()->_M_dispose(__a); + _M_data(__tmp); + } + catch (const __cxxabiv1::__forced_unwind&) + { throw; } + catch (...) + { /* swallow the exception */ } + } + template<typename _CharT, typename _Traits, typename _Alloc> typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: |