From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [216.205.24.124]) by sourceware.org (Postfix) with ESMTPS id 0131B3857029 for ; Tue, 16 Nov 2021 16:45:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 0131B3857029 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-525-v_zDsKDdMw-Xmcq1WJwJAQ-1; Tue, 16 Nov 2021 11:45:31 -0500 X-MC-Unique: v_zDsKDdMw-Xmcq1WJwJAQ-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 63EC0875047; Tue, 16 Nov 2021 16:45:30 +0000 (UTC) Received: from localhost (unknown [10.33.36.17]) by smtp.corp.redhat.com (Postfix) with ESMTP id 72BA019723; Tue, 16 Nov 2021 16:45:29 +0000 (UTC) From: Jonathan Wakely To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Cc: Michael de Lang Subject: [committed 2/2] libstdc++: Implement constexpr std::basic_string for C++20 Date: Tue, 16 Nov 2021 16:45:27 +0000 Message-Id: <20211116164527.3872136-2-jwakely@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII" X-Spam-Status: No, score=-13.8 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: libstdc++@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libstdc++ mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 16 Nov 2021 16:45:46 -0000 From: Michael de Lang Tested x86_64-linux, committed to trunk. This is only supported for the cxx11 ABI, not for COW strings. libstdc++-v3/ChangeLog: * include/bits/basic_string.h (basic_string, operator""s): Add constexpr for C++20. (basic_string::basic_string(basic_string&&)): Only copy initialized portion of the buffer. (basic_string::basic_string(basic_string&&, const Alloc&)): Likewise. * include/bits/basic_string.tcc (basic_string): Add constexpr for C++20. (basic_string::swap(basic_string&)): Only copy initialized portions of the buffers. (basic_string::_M_replace): Add constexpr implementation that doesn't depend on pointer comparisons. * include/bits/cow_string.h: Adjust comment. * include/ext/type_traits.h (__is_null_pointer): Add constexpr. * include/std/string (erase, erase_if): Add constexpr. * include/std/version (__cpp_lib_constexpr_string): Update value. * testsuite/21_strings/basic_string/cons/char/constexpr.cc: New test. * testsuite/21_strings/basic_string/cons/wchar_t/constexpr.cc: New test. * testsuite/21_strings/basic_string/literals/constexpr.cc: New test. * testsuite/21_strings/basic_string/modifiers/constexpr.cc: New test. * testsuite/21_strings/basic_string/modifiers/swap/char/constexpr.cc: New test. * testsuite/21_strings/basic_string/modifiers/swap/wchar_t/constexpr.cc: New test. * testsuite/21_strings/basic_string/version.cc: New test. --- libstdc++-v3/include/bits/basic_string.h | 274 ++++++++++++++++-- libstdc++-v3/include/bits/basic_string.tcc | 69 ++++- libstdc++-v3/include/bits/cow_string.h | 2 +- libstdc++-v3/include/ext/type_traits.h | 4 +- libstdc++-v3/include/std/string | 2 + libstdc++-v3/include/std/version | 6 +- .../basic_string/cons/char/constexpr.cc | 174 +++++++++++ .../basic_string/cons/wchar_t/constexpr.cc | 174 +++++++++++ .../basic_string/literals/constexpr.cc | 22 ++ .../basic_string/modifiers/constexpr.cc | 52 ++++ .../modifiers/swap/char/constexpr.cc | 49 ++++ .../modifiers/swap/wchar_t/constexpr.cc | 49 ++++ .../21_strings/basic_string/version.cc | 25 ++ 13 files changed, 869 insertions(+), 33 deletions(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/cons/char/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/literals/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/modifiers/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/char/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/wchar_t/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/version.cc diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index a6575fa9e26..b6945f1cdfb 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -57,12 +57,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _GLIBCXX_BEGIN_NAMESPACE_CXX11 #ifdef __cpp_lib_is_constant_evaluated -// Support P1032R1 in C++20 (but not P0980R1 yet). -# define __cpp_lib_constexpr_string 201811L +// Support P0980R1 in C++20. +# define __cpp_lib_constexpr_string 201907L #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED // Support P0426R1 changes to char_traits in C++17. # define __cpp_lib_constexpr_string 201611L -#elif __cplusplus > 201703L #endif /** @@ -131,6 +130,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _Res>; // Allows an implicit conversion to __sv_type. + _GLIBCXX20_CONSTEXPR static __sv_type _S_to_string_view(__sv_type __svt) noexcept { return __svt; } @@ -141,7 +141,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // is provided. struct __sv_wrapper { - explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { } + _GLIBCXX20_CONSTEXPR explicit + __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { } + __sv_type _M_sv; }; @@ -151,6 +153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __svw string view wrapper. * @param __a Allocator to use. */ + _GLIBCXX20_CONSTEXPR explicit basic_string(__sv_wrapper __svw, const _Alloc& __a) : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { } @@ -163,9 +166,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _Alloc_hider(pointer __dat, const _Alloc& __a = _Alloc()) : allocator_type(__a), _M_p(__dat) { } #else + _GLIBCXX20_CONSTEXPR _Alloc_hider(pointer __dat, const _Alloc& __a) : allocator_type(__a), _M_p(__dat) { } + _GLIBCXX20_CONSTEXPR _Alloc_hider(pointer __dat, _Alloc&& __a = _Alloc()) : allocator_type(std::move(__a)), _M_p(__dat) { } #endif @@ -184,18 +189,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 size_type _M_allocated_capacity; }; + _GLIBCXX20_CONSTEXPR void _M_data(pointer __p) { _M_dataplus._M_p = __p; } + _GLIBCXX20_CONSTEXPR void _M_length(size_type __length) { _M_string_length = __length; } + _GLIBCXX20_CONSTEXPR pointer _M_data() const { return _M_dataplus._M_p; } + _GLIBCXX20_CONSTEXPR pointer _M_local_data() { @@ -206,6 +215,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #endif } + _GLIBCXX20_CONSTEXPR const_pointer _M_local_data() const { @@ -216,10 +226,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #endif } + _GLIBCXX20_CONSTEXPR void _M_capacity(size_type __capacity) { _M_allocated_capacity = __capacity; } + _GLIBCXX20_CONSTEXPR void _M_set_length(size_type __n) { @@ -227,14 +239,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 traits_type::assign(_M_data()[__n], _CharT()); } + _GLIBCXX20_CONSTEXPR bool _M_is_local() const { return _M_data() == _M_local_data(); } // Create & Destroy + _GLIBCXX20_CONSTEXPR pointer _M_create(size_type&, size_type); + _GLIBCXX20_CONSTEXPR void _M_dispose() { @@ -242,6 +257,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _M_destroy(_M_allocated_capacity); } + _GLIBCXX20_CONSTEXPR void _M_destroy(size_type __size) throw() { _Alloc_traits::deallocate(_M_get_allocator(), _M_data(), __size + 1); } @@ -249,6 +265,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // _M_construct_aux is used to implement the 21.3.1 para 15 which // requires special behaviour if _InIterator is an integral type template + _GLIBCXX20_CONSTEXPR void _M_construct_aux(_InIterator __beg, _InIterator __end, std::__false_type) @@ -260,15 +277,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // _GLIBCXX_RESOLVE_LIB_DEFECTS // 438. Ambiguity in the "do the right thing" clause template + _GLIBCXX20_CONSTEXPR void _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type) { _M_construct_aux_2(static_cast(__beg), __end); } + _GLIBCXX20_CONSTEXPR void _M_construct_aux_2(size_type __req, _CharT __c) { _M_construct(__req, __c); } template + _GLIBCXX20_CONSTEXPR void _M_construct(_InIterator __beg, _InIterator __end) { @@ -278,6 +298,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // For Input Iterators, used in istreambuf_iterators, etc. template + _GLIBCXX20_CONSTEXPR void _M_construct(_InIterator __beg, _InIterator __end, std::input_iterator_tag); @@ -285,17 +306,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // For forward_iterators up to random_access_iterators, used for // string::iterator, _CharT*, etc. template + _GLIBCXX20_CONSTEXPR void _M_construct(_FwdIterator __beg, _FwdIterator __end, std::forward_iterator_tag); + _GLIBCXX20_CONSTEXPR void _M_construct(size_type __req, _CharT __c); + _GLIBCXX20_CONSTEXPR allocator_type& _M_get_allocator() { return _M_dataplus; } + _GLIBCXX20_CONSTEXPR const allocator_type& _M_get_allocator() const { return _M_dataplus; } @@ -316,6 +341,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 struct __enable_if_not_native_iterator<_Tp, false> { }; #endif + _GLIBCXX20_CONSTEXPR size_type _M_check(size_type __pos, const char* __s) const { @@ -326,6 +352,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return __pos; } + _GLIBCXX20_CONSTEXPR void _M_check_length(size_type __n1, size_type __n2, const char* __s) const { @@ -335,6 +362,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // NB: _M_limit doesn't check for a bad __pos value. + _GLIBCXX20_CONSTEXPR size_type _M_limit(size_type __pos, size_type __off) const _GLIBCXX_NOEXCEPT { @@ -352,6 +380,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // When __n = 1 way faster than the general multichar // traits_type::copy/move/assign. + _GLIBCXX20_CONSTEXPR static void _S_copy(_CharT* __d, const _CharT* __s, size_type __n) { @@ -361,6 +390,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 traits_type::copy(__d, __s, __n); } + _GLIBCXX20_CONSTEXPR static void _S_move(_CharT* __d, const _CharT* __s, size_type __n) { @@ -370,6 +400,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 traits_type::move(__d, __s, __n); } + _GLIBCXX20_CONSTEXPR static void _S_assign(_CharT* __d, size_type __n, _CharT __c) { @@ -382,6 +413,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // _S_copy_chars is a separate template to permit specialization // to optimize for the common case of pointers as iterators. template + _GLIBCXX20_CONSTEXPR static void _S_copy_chars(_CharT* __p, _Iterator __k1, _Iterator __k2) { @@ -389,24 +421,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 traits_type::assign(*__p, *__k1); // These types are off. } + _GLIBCXX20_CONSTEXPR static void _S_copy_chars(_CharT* __p, iterator __k1, iterator __k2) _GLIBCXX_NOEXCEPT { _S_copy_chars(__p, __k1.base(), __k2.base()); } + _GLIBCXX20_CONSTEXPR static void _S_copy_chars(_CharT* __p, const_iterator __k1, const_iterator __k2) _GLIBCXX_NOEXCEPT { _S_copy_chars(__p, __k1.base(), __k2.base()); } + _GLIBCXX20_CONSTEXPR static void _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2) _GLIBCXX_NOEXCEPT { _S_copy(__p, __k1, __k2 - __k1); } + _GLIBCXX20_CONSTEXPR static void _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2) _GLIBCXX_NOEXCEPT { _S_copy(__p, __k1, __k2 - __k1); } + _GLIBCXX20_CONSTEXPR static int _S_compare(size_type __n1, size_type __n2) _GLIBCXX_NOEXCEPT { @@ -420,13 +457,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 return int(__d); } + _GLIBCXX20_CONSTEXPR void _M_assign(const basic_string&); + _GLIBCXX20_CONSTEXPR void _M_mutate(size_type __pos, size_type __len1, const _CharT* __s, size_type __len2); + _GLIBCXX20_CONSTEXPR void _M_erase(size_type __pos, size_type __n); @@ -438,6 +478,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Default constructor creates an empty string. */ + _GLIBCXX20_CONSTEXPR basic_string() _GLIBCXX_NOEXCEPT_IF(is_nothrow_default_constructible<_Alloc>::value) : _M_dataplus(_M_local_data()) @@ -446,6 +487,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Construct an empty string using allocator @a a. */ + _GLIBCXX20_CONSTEXPR explicit basic_string(const _Alloc& __a) _GLIBCXX_NOEXCEPT : _M_dataplus(_M_local_data(), __a) @@ -455,6 +497,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Construct string with copy of value of @a __str. * @param __str Source string. */ + _GLIBCXX20_CONSTEXPR basic_string(const basic_string& __str) : _M_dataplus(_M_local_data(), _Alloc_traits::_S_select_on_copy(__str._M_get_allocator())) @@ -468,6 +511,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __pos Index of first character to copy from. * @param __a Allocator to use. */ + _GLIBCXX20_CONSTEXPR basic_string(const basic_string& __str, size_type __pos, const _Alloc& __a = _Alloc()) : _M_dataplus(_M_local_data(), __a) @@ -483,6 +527,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __pos Index of first character to copy from. * @param __n Number of characters to copy. */ + _GLIBCXX20_CONSTEXPR basic_string(const basic_string& __str, size_type __pos, size_type __n) : _M_dataplus(_M_local_data()) @@ -499,6 +544,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n Number of characters to copy. * @param __a Allocator to use. */ + _GLIBCXX20_CONSTEXPR basic_string(const basic_string& __str, size_type __pos, size_type __n, const _Alloc& __a) : _M_dataplus(_M_local_data(), __a) @@ -517,6 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * NB: @a __s must have at least @a __n characters, '\\0' * has no special meaning. */ + _GLIBCXX20_CONSTEXPR basic_string(const _CharT* __s, size_type __n, const _Alloc& __a = _Alloc()) : _M_dataplus(_M_local_data(), __a) @@ -532,6 +579,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // 3076. basic_string CTAD ambiguity template> #endif + _GLIBCXX20_CONSTEXPR basic_string(const _CharT* __s, const _Alloc& __a = _Alloc()) : _M_dataplus(_M_local_data(), __a) { @@ -552,6 +600,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // 3076. basic_string CTAD ambiguity template> #endif + _GLIBCXX20_CONSTEXPR basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc()) : _M_dataplus(_M_local_data(), __a) { _M_construct(__n, __c); } @@ -564,13 +613,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * The newly-created string contains the exact contents of @a __str. * @a __str is a valid, but unspecified string. */ + _GLIBCXX20_CONSTEXPR basic_string(basic_string&& __str) noexcept : _M_dataplus(_M_local_data(), std::move(__str._M_get_allocator())) { if (__str._M_is_local()) { traits_type::copy(_M_local_buf, __str._M_local_buf, - _S_local_capacity + 1); + __str.length() + 1); } else { @@ -591,14 +641,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __l std::initializer_list of characters. * @param __a Allocator to use (default is default allocator). */ + _GLIBCXX20_CONSTEXPR basic_string(initializer_list<_CharT> __l, const _Alloc& __a = _Alloc()) : _M_dataplus(_M_local_data(), __a) { _M_construct(__l.begin(), __l.end()); } + _GLIBCXX20_CONSTEXPR basic_string(const basic_string& __str, const _Alloc& __a) : _M_dataplus(_M_local_data(), __a) { _M_construct(__str.begin(), __str.end()); } + _GLIBCXX20_CONSTEXPR basic_string(basic_string&& __str, const _Alloc& __a) noexcept(_Alloc_traits::_S_always_equal()) : _M_dataplus(_M_local_data(), __a) @@ -606,7 +659,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 if (__str._M_is_local()) { traits_type::copy(_M_local_buf, __str._M_local_buf, - _S_local_capacity + 1); + __str.length() + 1); _M_length(__str.length()); __str._M_set_length(0); } @@ -639,6 +692,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #else template #endif + _GLIBCXX20_CONSTEXPR basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a = _Alloc()) : _M_dataplus(_M_local_data(), __a) @@ -653,6 +707,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __a Allocator to use. */ template> + _GLIBCXX20_CONSTEXPR basic_string(const _Tp& __t, size_type __pos, size_type __n, const _Alloc& __a = _Alloc()) : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { } @@ -663,6 +718,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __a Allocator to use (default is default allocator). */ template> + _GLIBCXX20_CONSTEXPR explicit basic_string(const _Tp& __t, const _Alloc& __a = _Alloc()) : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { } @@ -671,6 +727,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Destroy the string instance. */ + _GLIBCXX20_CONSTEXPR ~basic_string() { _M_dispose(); } @@ -678,6 +735,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Assign the value of @a str to this string. * @param __str Source string. */ + _GLIBCXX20_CONSTEXPR basic_string& operator=(const basic_string& __str) { @@ -688,6 +746,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Copy contents of @a s into this string. * @param __s Source null-terminated string. */ + _GLIBCXX20_CONSTEXPR basic_string& operator=(const _CharT* __s) { return this->assign(__s); } @@ -699,6 +758,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Assigning to a character makes this string length 1 and * (*this)[0] == @a c. */ + _GLIBCXX20_CONSTEXPR basic_string& operator=(_CharT __c) { @@ -716,6 +776,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ // _GLIBCXX_RESOLVE_LIB_DEFECTS // 2063. Contradictory requirements for string move assignment + _GLIBCXX20_CONSTEXPR basic_string& operator=(basic_string&& __str) noexcept(_Alloc_traits::_S_nothrow_move()) @@ -784,6 +845,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Set value to string constructed from initializer %list. * @param __l std::initializer_list. */ + _GLIBCXX20_CONSTEXPR basic_string& operator=(initializer_list<_CharT> __l) { @@ -798,6 +860,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __svt An object convertible to string_view. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> operator=(const _Tp& __svt) { return this->assign(__svt); } @@ -806,6 +869,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Convert to a string_view. * @return A string_view. */ + _GLIBCXX20_CONSTEXPR operator __sv_type() const noexcept { return __sv_type(data(), size()); } #endif // C++17 @@ -815,6 +879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write iterator that points to the first character in * the %string. */ + _GLIBCXX20_CONSTEXPR iterator begin() _GLIBCXX_NOEXCEPT { return iterator(_M_data()); } @@ -823,6 +888,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points to the first * character in the %string. */ + _GLIBCXX20_CONSTEXPR const_iterator begin() const _GLIBCXX_NOEXCEPT { return const_iterator(_M_data()); } @@ -831,6 +897,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write iterator that points one past the last * character in the %string. */ + _GLIBCXX20_CONSTEXPR iterator end() _GLIBCXX_NOEXCEPT { return iterator(_M_data() + this->size()); } @@ -839,6 +906,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points one past the * last character in the %string. */ + _GLIBCXX20_CONSTEXPR const_iterator end() const _GLIBCXX_NOEXCEPT { return const_iterator(_M_data() + this->size()); } @@ -848,6 +916,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * character in the %string. Iteration is done in reverse element * order. */ + _GLIBCXX20_CONSTEXPR reverse_iterator rbegin() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->end()); } @@ -857,6 +926,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to the last character in the %string. Iteration is done in * reverse element order. */ + _GLIBCXX20_CONSTEXPR const_reverse_iterator rbegin() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->end()); } @@ -866,6 +936,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first character in the %string. Iteration is done in reverse * element order. */ + _GLIBCXX20_CONSTEXPR reverse_iterator rend() _GLIBCXX_NOEXCEPT { return reverse_iterator(this->begin()); } @@ -875,6 +946,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to one before the first character in the %string. Iteration * is done in reverse element order. */ + _GLIBCXX20_CONSTEXPR const_reverse_iterator rend() const _GLIBCXX_NOEXCEPT { return const_reverse_iterator(this->begin()); } @@ -884,6 +956,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points to the first * character in the %string. */ + _GLIBCXX20_CONSTEXPR const_iterator cbegin() const noexcept { return const_iterator(this->_M_data()); } @@ -892,6 +965,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) iterator that points one past the * last character in the %string. */ + _GLIBCXX20_CONSTEXPR const_iterator cend() const noexcept { return const_iterator(this->_M_data() + this->size()); } @@ -901,6 +975,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to the last character in the %string. Iteration is done in * reverse element order. */ + _GLIBCXX20_CONSTEXPR const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->end()); } @@ -910,6 +985,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * to one before the first character in the %string. Iteration * is done in reverse element order. */ + _GLIBCXX20_CONSTEXPR const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->begin()); } @@ -919,17 +995,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // Capacity: /// Returns the number of characters in the string, not including any /// null-termination. + _GLIBCXX20_CONSTEXPR size_type size() const _GLIBCXX_NOEXCEPT { return _M_string_length; } /// Returns the number of characters in the string, not including any /// null-termination. + _GLIBCXX20_CONSTEXPR size_type length() const _GLIBCXX_NOEXCEPT { return _M_string_length; } /// Returns the size() of the largest possible %string. + _GLIBCXX20_CONSTEXPR size_type max_size() const _GLIBCXX_NOEXCEPT { return (_Alloc_traits::max_size(_M_get_allocator()) - 1) / 2; } @@ -944,6 +1023,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * %string's current size the %string is truncated, otherwise * the %string is extended and new elements are %set to @a __c. */ + _GLIBCXX20_CONSTEXPR void resize(size_type __n, _CharT __c); @@ -957,6 +1037,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * are default-constructed. For basic types such as char, this means * setting them to 0. */ + _GLIBCXX20_CONSTEXPR void resize(size_type __n) { this->resize(__n, _CharT()); } @@ -965,6 +1046,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" /// A non-binding request to reduce capacity() to size(). + _GLIBCXX20_CONSTEXPR void shrink_to_fit() noexcept { reserve(); } @@ -982,6 +1064,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns the total number of characters that the %string can hold * before needing to allocate more memory. */ + _GLIBCXX20_CONSTEXPR size_type capacity() const _GLIBCXX_NOEXCEPT { @@ -1006,6 +1089,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * prevent a possible reallocation of memory and copying of %string * data. */ + _GLIBCXX20_CONSTEXPR void reserve(size_type __res_arg); @@ -1015,12 +1099,14 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201703L [[deprecated("use shrink_to_fit() instead")]] #endif + _GLIBCXX20_CONSTEXPR void reserve(); /** * Erases the string, making it empty. */ + _GLIBCXX20_CONSTEXPR void clear() _GLIBCXX_NOEXCEPT { _M_set_length(0); } @@ -1029,7 +1115,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns true if the %string is empty. Equivalent to * *this == "". */ - _GLIBCXX_NODISCARD bool + _GLIBCXX_NODISCARD _GLIBCXX20_CONSTEXPR + bool empty() const _GLIBCXX_NOEXCEPT { return this->size() == 0; } @@ -1044,6 +1131,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range lookups are not defined. (For checked lookups * see at().) */ + _GLIBCXX20_CONSTEXPR const_reference operator[] (size_type __pos) const _GLIBCXX_NOEXCEPT { @@ -1061,6 +1149,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range lookups are not defined. (For checked lookups * see at().) */ + _GLIBCXX20_CONSTEXPR reference operator[](size_type __pos) { @@ -1082,6 +1171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first checked that it is in the range of the string. The function * throws out_of_range if the check fails. */ + _GLIBCXX20_CONSTEXPR const_reference at(size_type __n) const { @@ -1103,6 +1193,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * first checked that it is in the range of the string. The function * throws out_of_range if the check fails. */ + _GLIBCXX20_CONSTEXPR reference at(size_type __n) { @@ -1119,6 +1210,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write reference to the data at the first * element of the %string. */ + _GLIBCXX20_CONSTEXPR reference front() noexcept { @@ -1130,6 +1222,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) reference to the data at the first * element of the %string. */ + _GLIBCXX20_CONSTEXPR const_reference front() const noexcept { @@ -1141,6 +1234,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read/write reference to the data at the last * element of the %string. */ + _GLIBCXX20_CONSTEXPR reference back() noexcept { @@ -1152,6 +1246,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Returns a read-only (constant) reference to the data at the * last element of the %string. */ + _GLIBCXX20_CONSTEXPR const_reference back() const noexcept { @@ -1166,6 +1261,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __str The string to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& operator+=(const basic_string& __str) { return this->append(__str); } @@ -1175,6 +1271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __s The C string to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& operator+=(const _CharT* __s) { return this->append(__s); } @@ -1184,6 +1281,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __c The character to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& operator+=(_CharT __c) { @@ -1197,6 +1295,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __l The initializer_list of characters to be appended. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& operator+=(initializer_list<_CharT> __l) { return this->append(__l.begin(), __l.size()); } @@ -1209,6 +1308,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> operator+=(const _Tp& __svt) { return this->append(__svt); } @@ -1219,6 +1319,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __str The string to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& append(const basic_string& __str) { return _M_append(__str._M_data(), __str.size()); } @@ -1236,6 +1337,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * than the number of available characters in @a __str, the * remainder of @a __str is appended. */ + _GLIBCXX20_CONSTEXPR basic_string& append(const basic_string& __str, size_type __pos, size_type __n = npos) { return _M_append(__str._M_data() @@ -1248,6 +1350,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& append(const _CharT* __s, size_type __n) { @@ -1261,6 +1364,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __s The C string to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& append(const _CharT* __s) { @@ -1278,6 +1382,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Appends __n copies of __c to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& append(size_type __n, _CharT __c) { return _M_replace_aux(this->size(), size_type(0), __n, __c); } @@ -1288,6 +1393,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __l The initializer_list of characters to append. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& append(initializer_list<_CharT> __l) { return this->append(__l.begin(), __l.size()); } @@ -1304,6 +1410,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus >= 201103L template> + _GLIBCXX20_CONSTEXPR #else template #endif @@ -1318,6 +1425,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> append(const _Tp& __svt) { @@ -1333,6 +1441,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> append(const _Tp& __svt, size_type __pos, size_type __n = npos) { @@ -1347,6 +1456,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Append a single character. * @param __c Character to append. */ + _GLIBCXX20_CONSTEXPR void push_back(_CharT __c) { @@ -1362,6 +1472,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __str Source string to use. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(const basic_string& __str) { @@ -1407,6 +1518,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This function sets this string to the exact contents of @a __str. * @a __str is a valid, but unspecified string. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(basic_string&& __str) noexcept(_Alloc_traits::_S_nothrow_move()) @@ -1430,6 +1542,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * is larger than the number of available characters in @a * __str, the remainder of @a __str is used. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(const basic_string& __str, size_type __pos, size_type __n = npos) { return _M_replace(size_type(0), this->size(), __str._M_data() @@ -1446,6 +1559,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s. If @a __n is is larger than the number of * available characters in @a __s, the remainder of @a __s is used. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(const _CharT* __s, size_type __n) { @@ -1462,6 +1576,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * The data is copied, so there is no dependence on @a __s once the * function returns. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(const _CharT* __s) { @@ -1479,6 +1594,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This function sets the value of this string to @a __n copies of * character @a __c. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(size_type __n, _CharT __c) { return _M_replace_aux(size_type(0), this->size(), __n, __c); } @@ -1494,6 +1610,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus >= 201103L template> + _GLIBCXX20_CONSTEXPR #else template #endif @@ -1507,6 +1624,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __l The initializer_list of characters to assign. * @return Reference to this string. */ + _GLIBCXX20_CONSTEXPR basic_string& assign(initializer_list<_CharT> __l) { return this->assign(__l.begin(), __l.size()); } @@ -1519,6 +1637,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> assign(const _Tp& __svt) { @@ -1534,6 +1653,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> assign(const _Tp& __svt, size_type __pos, size_type __n = npos) { @@ -1561,6 +1681,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * length_error is thrown. The value of the string doesn't * change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR iterator insert(const_iterator __p, size_type __n, _CharT __c) { @@ -1605,6 +1726,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ template> + _GLIBCXX20_CONSTEXPR iterator insert(const_iterator __p, _InputIterator __beg, _InputIterator __end) { @@ -1639,6 +1761,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __l The initializer_list of characters to insert. * @throw std::length_error If new length exceeds @c max_size(). */ + _GLIBCXX20_CONSTEXPR iterator insert(const_iterator __p, initializer_list<_CharT> __l) { return this->insert(__p, __l.begin(), __l.end()); } @@ -1666,6 +1789,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * length_error is thrown. The value of the string doesn't * change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& insert(size_type __pos1, const basic_string& __str) { return this->replace(__pos1, size_type(0), @@ -1689,6 +1813,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * beyond the end of @a __str, out_of_range is thrown. The * value of the string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& insert(size_type __pos1, const basic_string& __str, size_type __pos2, size_type __n = npos) @@ -1712,6 +1837,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * end(), out_of_range is thrown. The value of the string * doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& insert(size_type __pos, const _CharT* __s, size_type __n) { return this->replace(__pos, size_type(0), __s, __n); } @@ -1731,6 +1857,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * thrown. The value of the string doesn't change if an error is * thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& insert(size_type __pos, const _CharT* __s) { @@ -1755,6 +1882,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range is thrown. The value of the string doesn't * change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& insert(size_type __pos, size_type __n, _CharT __c) { return _M_replace_aux(_M_check(__pos, "basic_string::insert"), @@ -1773,6 +1901,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range is thrown. The value of the string doesn't * change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR iterator insert(__const_iterator __p, _CharT __c) { @@ -1790,6 +1919,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> insert(size_type __pos, const _Tp& __svt) { @@ -1806,6 +1936,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> insert(size_type __pos1, const _Tp& __svt, size_type __pos2, size_type __n = npos) @@ -1833,6 +1964,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * out_of_range is thrown. The value of the string doesn't * change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& erase(size_type __pos = 0, size_type __n = npos) { @@ -1852,6 +1984,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Removes the character at @a __position from this string. The value * of the string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR iterator erase(__const_iterator __position) { @@ -1871,6 +2004,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Removes the characters in the range [first,last) from this string. * The value of the string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR iterator erase(__const_iterator __first, __const_iterator __last) { @@ -1890,6 +2024,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * The string must be non-empty. */ + _GLIBCXX20_CONSTEXPR void pop_back() noexcept { @@ -1915,6 +2050,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * is thrown. The value of the string doesn't change if an * error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(size_type __pos, size_type __n, const basic_string& __str) { return this->replace(__pos, __n, __str._M_data(), __str.size()); } @@ -1937,6 +2073,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * result exceeds max_size(), length_error is thrown. The value of the * string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) @@ -1962,6 +2099,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * thrown. The value of the string doesn't change if an error * is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) @@ -1987,6 +2125,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * length_error is thrown. The value of the string doesn't * change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(size_type __pos, size_type __n1, const _CharT* __s) { @@ -2011,6 +2150,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * thrown. The value of the string doesn't change if an error * is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c) { return _M_replace_aux(_M_check(__pos, "basic_string::replace"), @@ -2029,6 +2169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * exceeds max_size(), length_error is thrown. The value of * the string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, const basic_string& __str) @@ -2049,6 +2190,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * The value of the string doesn't change if an error is * thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __s, size_type __n) @@ -2071,6 +2213,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * result exceeds max_size(), length_error is thrown. The * value of the string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __s) { @@ -2092,6 +2235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * result exceeds max_size(), length_error is thrown. The * value of the string doesn't change if an error is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, size_type __n, _CharT __c) @@ -2119,6 +2263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus >= 201103L template> + _GLIBCXX20_CONSTEXPR basic_string& replace(const_iterator __i1, const_iterator __i2, _InputIterator __k1, _InputIterator __k2) @@ -2149,6 +2294,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 // Specializations for the common case of pointer and iterator: // useful to avoid the overhead of temporary buffering in _M_replace. + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, _CharT* __k1, _CharT* __k2) @@ -2160,6 +2306,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 __k1, __k2 - __k1); } + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, const _CharT* __k1, const _CharT* __k2) @@ -2171,6 +2318,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 __k1, __k2 - __k1); } + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, iterator __k1, iterator __k2) @@ -2182,6 +2330,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 __k1.base(), __k2 - __k1); } + _GLIBCXX20_CONSTEXPR basic_string& replace(__const_iterator __i1, __const_iterator __i2, const_iterator __k1, const_iterator __k2) @@ -2208,6 +2357,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * The value of the string doesn't change if an error is * thrown. */ + _GLIBCXX20_CONSTEXPR basic_string& replace(const_iterator __i1, const_iterator __i2, initializer_list<_CharT> __l) { return this->replace(__i1, __i2, __l.begin(), __l.size()); } @@ -2222,6 +2372,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> replace(size_type __pos, size_type __n, const _Tp& __svt) { @@ -2239,6 +2390,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> replace(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) @@ -2260,6 +2412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Reference to this string. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, basic_string&> replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt) { @@ -2270,25 +2423,30 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 private: template + _GLIBCXX20_CONSTEXPR basic_string& _M_replace_dispatch(const_iterator __i1, const_iterator __i2, _Integer __n, _Integer __val, __true_type) { return _M_replace_aux(__i1 - begin(), __i2 - __i1, __n, __val); } template + _GLIBCXX20_CONSTEXPR basic_string& _M_replace_dispatch(const_iterator __i1, const_iterator __i2, _InputIterator __k1, _InputIterator __k2, __false_type); + _GLIBCXX20_CONSTEXPR basic_string& _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2, _CharT __c); + _GLIBCXX20_CONSTEXPR basic_string& _M_replace(size_type __pos, size_type __len1, const _CharT* __s, const size_type __len2); + _GLIBCXX20_CONSTEXPR basic_string& _M_append(const _CharT* __s, size_type __n); @@ -2306,6 +2464,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * C string @a __s. If @a __pos is %greater than size(), * out_of_range is thrown. */ + _GLIBCXX20_CONSTEXPR size_type copy(_CharT* __s, size_type __n, size_type __pos = 0) const; @@ -2316,6 +2475,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * Exchanges the contents of this string with that of @a __s in constant * time. */ + _GLIBCXX20_CONSTEXPR void swap(basic_string& __s) _GLIBCXX_NOEXCEPT; @@ -2326,6 +2486,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This is a handle to internal data. Do not modify or dire things may * happen. */ + _GLIBCXX20_CONSTEXPR const _CharT* c_str() const _GLIBCXX_NOEXCEPT { return _M_data(); } @@ -2338,6 +2499,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * allows modifying the contents use @c &str[0] instead, * (or in C++17 the non-const @c str.data() overload). */ + _GLIBCXX20_CONSTEXPR const _CharT* data() const _GLIBCXX_NOEXCEPT { return _M_data(); } @@ -2349,6 +2511,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * This is a pointer to the character sequence held by the string. * Modifying the characters in the sequence is allowed. */ + _GLIBCXX20_CONSTEXPR _CharT* data() noexcept { return _M_data(); } @@ -2357,6 +2520,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Return copy of allocator used to construct this string. */ + _GLIBCXX20_CONSTEXPR allocator_type get_allocator() const _GLIBCXX_NOEXCEPT { return _M_get_allocator(); } @@ -2373,6 +2537,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it begins. If not found, returns * npos. */ + _GLIBCXX20_CONSTEXPR size_type find(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2387,6 +2552,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it begins. If not * found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2400,6 +2566,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2419,6 +2586,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * __s within this string. If found, returns the index where * it begins. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { @@ -2436,6 +2604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; @@ -2449,6 +2618,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * __str within this string. If found, returns the index where * it begins. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type rfind(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2462,6 +2632,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> rfind(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2483,6 +2654,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it begins. If not found, returns * npos. */ + _GLIBCXX20_CONSTEXPR size_type rfind(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2497,6 +2669,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @a __s within this string. If found, returns the index * where it begins. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type rfind(const _CharT* __s, size_type __pos = npos) const { @@ -2514,6 +2687,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type rfind(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; @@ -2528,6 +2702,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_of(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2542,6 +2717,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of first occurrence. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_first_of(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2563,6 +2739,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * found, returns the index where it was found. If not found, * returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2577,6 +2754,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_of(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2597,6 +2775,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note: equivalent to find(__c, __pos). */ + _GLIBCXX20_CONSTEXPR size_type find_first_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT { return this->find(__c, __pos); } @@ -2612,6 +2791,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_of(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2626,6 +2806,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of last occurrence. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_last_of(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2647,6 +2828,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * found, returns the index where it was found. If not found, * returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2661,6 +2843,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * characters of @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_of(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2681,6 +2864,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * * Note: equivalent to rfind(__c, __pos). */ + _GLIBCXX20_CONSTEXPR size_type find_last_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT { return this->rfind(__c, __pos); } @@ -2695,6 +2879,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * in @a __str within this string. If found, returns the index where it * was found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const basic_string& __str, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2710,6 +2895,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 */ template _If_sv<_Tp, size_type> + _GLIBCXX20_CONSTEXPR find_first_not_of(const _Tp& __svt, size_type __pos = 0) const noexcept(is_same<_Tp, __sv_type>::value) { @@ -2730,6 +2916,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * this string. If found, returns the index where it was * found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2744,6 +2931,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * contained in @a __s within this string. If found, returns * the index where it was found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_not_of(const _CharT* __s, size_type __pos = 0) const _GLIBCXX_NOEXCEPT @@ -2762,6 +2950,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * other than @a __c within this string. If found, returns the * index where it was found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_first_not_of(_CharT __c, size_type __pos = 0) const _GLIBCXX_NOEXCEPT; @@ -2777,6 +2966,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const basic_string& __str, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2791,6 +2981,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of last occurrence. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, size_type> find_last_not_of(const _Tp& __svt, size_type __pos = npos) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2812,6 +3003,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If found, returns the index where it was found. If not found, * returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const _GLIBCXX_NOEXCEPT; @@ -2826,6 +3018,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * returns the index where it was found. If not found, returns * npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_not_of(const _CharT* __s, size_type __pos = npos) const _GLIBCXX_NOEXCEPT @@ -2844,6 +3037,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @a __c within this string. If found, returns the index where it was * found. If not found, returns npos. */ + _GLIBCXX20_CONSTEXPR size_type find_last_not_of(_CharT __c, size_type __pos = npos) const _GLIBCXX_NOEXCEPT; @@ -2860,6 +3054,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * short, use the remainder of the characters. If @a __pos is * beyond the end of the string, out_of_range is thrown. */ + _GLIBCXX20_CONSTEXPR basic_string substr(size_type __pos = 0, size_type __n = npos) const { return basic_string(*this, @@ -2879,6 +3074,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If the result of the comparison is nonzero returns it, * otherwise the shorter one is ordered first. */ + _GLIBCXX20_CONSTEXPR int compare(const basic_string& __str) const { @@ -2899,6 +3095,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(const _Tp& __svt) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2923,6 +3120,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos, size_type __n, const _Tp& __svt) const noexcept(is_same<_Tp, __sv_type>::value) @@ -2942,6 +3140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Integer < 0, 0, or > 0. */ template + _GLIBCXX20_CONSTEXPR _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const @@ -2972,6 +3171,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * result of the comparison is nonzero returns it, otherwise * the shorter one is ordered first. */ + _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n, const basic_string& __str) const; @@ -2998,6 +3198,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * If the result of the comparison is nonzero returns it, * otherwise the shorter one is ordered first. */ + _GLIBCXX20_CONSTEXPR int compare(size_type __pos1, size_type __n1, const basic_string& __str, size_type __pos2, size_type __n2 = npos) const; @@ -3016,6 +3217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * comparison is nonzero returns it, otherwise the shorter one is * ordered first. */ + _GLIBCXX20_CONSTEXPR int compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT; @@ -3040,6 +3242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * the comparison is nonzero returns it, otherwise the shorter * one is ordered first. */ + _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n1, const _CharT* __s) const; @@ -3067,46 +3270,47 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * NB: s must have at least n2 characters, '\\0' has * no special meaning. */ + _GLIBCXX20_CONSTEXPR int compare(size_type __pos, size_type __n1, const _CharT* __s, size_type __n2) const; -#if __cplusplus > 201703L - bool +#if __cplusplus >= 202002L + constexpr bool starts_with(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } - bool + constexpr bool starts_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } - bool + constexpr bool starts_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).starts_with(__x); } - bool + constexpr bool ends_with(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } - bool + constexpr bool ends_with(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } - bool + constexpr bool ends_with(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).ends_with(__x); } #endif // C++20 #if __cplusplus > 202002L - bool + constexpr bool contains(basic_string_view<_CharT, _Traits> __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } - bool + constexpr bool contains(_CharT __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } - bool + constexpr bool contains(const _CharT* __x) const noexcept { return __sv_type(this->data(), this->size()).contains(__x); } #endif // C++23 @@ -3160,6 +3364,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with value of @a __lhs followed by @a __rhs. */ template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3176,6 +3381,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with value of @a __lhs followed by @a __rhs. */ template + _GLIBCXX20_CONSTEXPR basic_string<_CharT,_Traits,_Alloc> operator+(const _CharT* __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); @@ -3187,6 +3393,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template + _GLIBCXX20_CONSTEXPR basic_string<_CharT,_Traits,_Alloc> operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs); @@ -3197,6 +3404,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3213,6 +3421,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return New string with @a __lhs followed by @a __rhs. */ template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs) { @@ -3225,18 +3434,21 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus >= 201103L template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) { return std::move(__lhs.append(__rhs)); } template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) @@ -3259,24 +3471,28 @@ _GLIBCXX_END_NAMESPACE_CXX11 } template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(const _CharT* __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, __lhs)); } template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(_CharT __lhs, basic_string<_CharT, _Traits, _Alloc>&& __rhs) { return std::move(__rhs.insert(0, 1, __lhs)); } template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, const _CharT* __rhs) { return std::move(__lhs.append(__rhs)); } template + _GLIBCXX20_CONSTEXPR inline basic_string<_CharT, _Traits, _Alloc> operator+(basic_string<_CharT, _Traits, _Alloc>&& __lhs, _CharT __rhs) @@ -3291,6 +3507,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise. */ template + _GLIBCXX20_CONSTEXPR inline bool operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -3298,6 +3515,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 { return __lhs.compare(__rhs) == 0; } template + _GLIBCXX20_CONSTEXPR inline typename __gnu_cxx::__enable_if<__is_char<_CharT>::__value, bool>::__type operator==(const basic_string<_CharT>& __lhs, @@ -3313,6 +3531,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @return True if @a __lhs.compare(@a __rhs) == 0. False otherwise. */ template + _GLIBCXX20_CONSTEXPR inline bool operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) @@ -3327,6 +3546,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * greater than, or incomparable with `__rhs`. */ template + _GLIBCXX20_CONSTEXPR inline auto operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) noexcept @@ -3341,6 +3561,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * greater than, or incomparable with `__rhs`. */ template + _GLIBCXX20_CONSTEXPR inline auto operator<=>(const basic_string<_CharT, _Traits, _Alloc>& __lhs, const _CharT* __rhs) noexcept @@ -3558,6 +3779,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 * Exchanges the contents of @a __lhs and @a __rhs in constant time. */ template + _GLIBCXX20_CONSTEXPR inline void swap(basic_string<_CharT, _Traits, _Alloc>& __lhs, basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -4034,33 +4256,41 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wliteral-suffix" - _GLIBCXX_DEFAULT_ABI_TAG + +#if __cpp_lib_constexpr_string >= 201907L +# define _GLIBCXX_STRING_CONSTEXPR constexpr +#else +# define _GLIBCXX_STRING_CONSTEXPR +#endif + + _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR inline basic_string operator""s(const char* __str, size_t __len) { return basic_string{__str, __len}; } - _GLIBCXX_DEFAULT_ABI_TAG + _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR inline basic_string operator""s(const wchar_t* __str, size_t __len) { return basic_string{__str, __len}; } #ifdef _GLIBCXX_USE_CHAR8_T - _GLIBCXX_DEFAULT_ABI_TAG + _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR inline basic_string operator""s(const char8_t* __str, size_t __len) { return basic_string{__str, __len}; } #endif - _GLIBCXX_DEFAULT_ABI_TAG + _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR inline basic_string operator""s(const char16_t* __str, size_t __len) { return basic_string{__str, __len}; } - _GLIBCXX_DEFAULT_ABI_TAG + _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_STRING_CONSTEXPR inline basic_string operator""s(const char32_t* __str, size_t __len) { return basic_string{__str, __len}; } +#undef _GLIBCXX_STRING_CONSTEXPR #pragma GCC diagnostic pop } // inline namespace string_literals } // inline namespace literals diff --git a/libstdc++-v3/include/bits/basic_string.tcc b/libstdc++-v3/include/bits/basic_string.tcc index 98c386239f9..5743770b42a 100644 --- a/libstdc++-v3/include/bits/basic_string.tcc +++ b/libstdc++-v3/include/bits/basic_string.tcc @@ -54,6 +54,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION basic_string<_CharT, _Traits, _Alloc>::npos; template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: swap(basic_string& __s) _GLIBCXX_NOEXCEPT @@ -70,16 +71,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { _CharT __tmp_data[_S_local_capacity + 1]; traits_type::copy(__tmp_data, __s._M_local_buf, - _S_local_capacity + 1); + __s.length() + 1); traits_type::copy(__s._M_local_buf, _M_local_buf, - _S_local_capacity + 1); + length() + 1); traits_type::copy(_M_local_buf, __tmp_data, - _S_local_capacity + 1); + __s.length() + 1); } else if (__s.length()) { traits_type::copy(_M_local_buf, __s._M_local_buf, - _S_local_capacity + 1); + __s.length() + 1); _M_length(__s.length()); __s._M_set_length(0); return; @@ -87,7 +88,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else if (length()) { traits_type::copy(__s._M_local_buf, _M_local_buf, - _S_local_capacity + 1); + length() + 1); __s._M_length(length()); _M_set_length(0); return; @@ -97,7 +98,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION { const size_type __tmp_capacity = __s._M_allocated_capacity; traits_type::copy(__s._M_local_buf, _M_local_buf, - _S_local_capacity + 1); + length() + 1); _M_data(__s._M_data()); __s._M_data(__s._M_local_buf); _M_capacity(__tmp_capacity); @@ -108,7 +109,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (__s._M_is_local()) { traits_type::copy(_M_local_buf, __s._M_local_buf, - _S_local_capacity + 1); + __s.length() + 1); __s._M_data(_M_data()); _M_data(_M_local_buf); } @@ -128,6 +129,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::pointer basic_string<_CharT, _Traits, _Alloc>:: _M_create(size_type& __capacity, size_type __old_capacity) @@ -159,6 +161,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // pointers, calling for a different coding style. template template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: _M_construct(_InIterator __beg, _InIterator __end, @@ -202,6 +205,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: _M_construct(_InIterator __beg, _InIterator __end, @@ -233,6 +237,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: _M_construct(size_type __n, _CharT __c) @@ -250,6 +255,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: _M_assign(const basic_string& __str) @@ -276,6 +282,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: reserve(size_type __res) @@ -296,6 +303,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: _M_mutate(size_type __pos, size_type __len1, const _CharT* __s, @@ -320,6 +328,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: _M_erase(size_type __pos, size_type __n) @@ -333,6 +342,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: reserve() @@ -368,6 +378,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR void basic_string<_CharT, _Traits, _Alloc>:: resize(size_type __n, _CharT __c) @@ -380,6 +391,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: _M_append(const _CharT* __s, size_type __n) @@ -400,6 +412,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: _M_replace_dispatch(const_iterator __i1, const_iterator __i2, @@ -415,6 +428,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2, @@ -444,6 +458,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc>& basic_string<_CharT, _Traits, _Alloc>:: _M_replace(size_type __pos, size_type __len1, const _CharT* __s, @@ -459,6 +474,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION pointer __p = this->_M_data() + __pos; const size_type __how_much = __old_size - __pos - __len1; +#if __cpp_lib_is_constant_evaluated + if (__builtin_is_constant_evaluated()) + { + auto __newp = this->_M_get_allocator().allocate(__new_size); + _S_copy(__newp, this->_M_data(), __pos); + _S_copy(__newp + __pos, __s, __len2); + _S_copy(__newp + __pos + __len2, __p + __len1, __how_much); + _S_copy(this->_M_data(), __newp, __new_size); + this->_M_get_allocator().deallocate(__newp, __new_size); + } + else +#endif if (_M_disjunct(__s)) { if (__how_much && __len1 != __len2) @@ -502,6 +529,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: copy(_CharT* __s, size_type __n, size_type __pos) const @@ -535,7 +563,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION else __p = _M_data(); struct _Terminator { - ~_Terminator() { _M_this->_M_set_length(_M_r); } + constexpr ~_Terminator() { _M_this->_M_set_length(_M_r); } basic_string* _M_this; size_type _M_r; }; @@ -548,7 +576,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #endif // _GLIBCXX_USE_CXX11_ABI +#if __cpp_lib_constexpr_string >= 201907L +# define _GLIBCXX_STRING_CONSTEXPR constexpr +#else +# define _GLIBCXX_STRING_CONSTEXPR +#endif + template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc> operator+(const _CharT* __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) @@ -569,6 +604,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR basic_string<_CharT, _Traits, _Alloc> operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) { @@ -587,6 +623,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find(const _CharT* __s, size_type __pos, size_type __n) const @@ -623,6 +660,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT @@ -641,6 +679,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: rfind(const _CharT* __s, size_type __pos, size_type __n) const @@ -663,6 +702,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT @@ -680,6 +720,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_first_of(const _CharT* __s, size_type __pos, size_type __n) const @@ -696,6 +737,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_last_of(const _CharT* __s, size_type __pos, size_type __n) const @@ -718,6 +760,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const @@ -731,6 +774,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT @@ -742,6 +786,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const @@ -764,6 +809,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR typename basic_string<_CharT, _Traits, _Alloc>::size_type basic_string<_CharT, _Traits, _Alloc>:: find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT @@ -784,6 +830,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR int basic_string<_CharT, _Traits, _Alloc>:: compare(size_type __pos, size_type __n, const basic_string& __str) const @@ -799,6 +846,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR int basic_string<_CharT, _Traits, _Alloc>:: compare(size_type __pos1, size_type __n1, const basic_string& __str, @@ -817,6 +865,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR int basic_string<_CharT, _Traits, _Alloc>:: compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT @@ -832,6 +881,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR int basic_string <_CharT, _Traits, _Alloc>:: compare(size_type __pos, size_type __n1, const _CharT* __s) const @@ -848,6 +898,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX_STRING_CONSTEXPR int basic_string <_CharT, _Traits, _Alloc>:: compare(size_type __pos, size_type __n1, const _CharT* __s, @@ -863,6 +914,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return __r; } +#undef _GLIBCXX_STRING_CONSTEXPR + // 21.3.7.9 basic_string::getline and operators template basic_istream<_CharT, _Traits>& diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h index f0540128364..bafca7bb313 100644 --- a/libstdc++-v3/include/bits/cow_string.h +++ b/libstdc++-v3/include/bits/cow_string.h @@ -35,7 +35,7 @@ #if ! _GLIBCXX_USE_CXX11_ABI #ifdef __cpp_lib_is_constant_evaluated -// Support P1032R1 in C++20 (but not P0980R1 yet). +// Support P1032R1 in C++20 (but not P0980R1 for COW strings). # define __cpp_lib_constexpr_string 201811L #elif __cplusplus >= 201703L && _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED // Support P0426R1 changes to char_traits in C++17. diff --git a/libstdc++-v3/include/ext/type_traits.h b/libstdc++-v3/include/ext/type_traits.h index fed78d3a527..3b41cf307a4 100644 --- a/libstdc++-v3/include/ext/type_traits.h +++ b/libstdc++-v3/include/ext/type_traits.h @@ -148,17 +148,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // For use in string and vstring. template + _GLIBCXX_CONSTEXPR inline bool __is_null_pointer(_Type* __ptr) { return __ptr == 0; } template + _GLIBCXX_CONSTEXPR inline bool __is_null_pointer(_Type) { return false; } #if __cplusplus >= 201103L - inline bool + constexpr bool __is_null_pointer(std::nullptr_t) { return true; } #endif diff --git a/libstdc++-v3/include/std/string b/libstdc++-v3/include/std/string index af840e887d5..1c5d1800c15 100644 --- a/libstdc++-v3/include/std/string +++ b/libstdc++-v3/include/std/string @@ -116,6 +116,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template + _GLIBCXX20_CONSTEXPR inline typename basic_string<_CharT, _Traits, _Alloc>::size_type erase_if(basic_string<_CharT, _Traits, _Alloc>& __cont, _Predicate __pred) { @@ -129,6 +130,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR inline typename basic_string<_CharT, _Traits, _Alloc>::size_type erase(basic_string<_CharT, _Traits, _Alloc>& __cont, const _Up& __value) { diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 0930de82efa..fd7e1258543 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -232,7 +232,11 @@ #define __cpp_lib_constexpr_memory 201811L #define __cpp_lib_constexpr_numeric 201911L #ifdef __cpp_lib_is_constant_evaluated -# define __cpp_lib_constexpr_string 201811L +# if _GLIBCXX_USE_CXX11_ABI +# define __cpp_lib_constexpr_string 201907L +# else +# define __cpp_lib_constexpr_string 201811L +# endif #endif #define __cpp_lib_constexpr_string_view 201811L #define __cpp_lib_constexpr_tuple 201811L diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/constexpr.cc new file mode 100644 index 00000000000..191ff1cb379 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/char/constexpr.cc @@ -0,0 +1,174 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } +// { dg-require-effective-target cxx11-abi } + +#include + +#ifndef __cpp_lib_constexpr_string +# error "Feature-test macro for constexpr std::string missing in " +#elif __cpp_lib_constexpr_string != 201907L +# error "Feature-test macro for constexpr std::string has wrong value in " +#endif + +#include + +using C = char; +using T = std::char_traits; + +template +struct Alloc : std::allocator +{ + using std::allocator::allocator; + + constexpr explicit Alloc(int p) : personality(p) { } + + template + constexpr Alloc(const Alloc& a) : personality(a.personality) { } + + int personality = 0; + + constexpr Alloc select_on_container_copy_construction() const + { return Alloc(-1); } + + constexpr bool operator==(const Alloc& a) const noexcept + { return personality == a.personality; } +}; + +constexpr bool +test_default_ctor() +{ + std::basic_string s0; + VERIFY( s0.empty() ); + + std::basic_string s1(std::allocator{}); + VERIFY( s1.empty() ); + + std::basic_string> s2; + VERIFY( s2.empty() ); + + std::basic_string> s3(Alloc(3)); + VERIFY( s3.empty() ); + VERIFY( s3.get_allocator().personality == 3 ); + + return true; +} + +static_assert( test_default_ctor() ); + +constexpr bool +test_cstr() +{ + const C cs[] = "This has an embedded \0 null"; + const auto len = (sizeof(cs) - 1)/sizeof(C); + + std::basic_string s1(cs); + VERIFY( s1.length() == 21 ); + std::basic_string s2(cs, std::allocator{}); + VERIFY( s2 == s1 ); + + std::basic_string s3(cs, len); + VERIFY( s3.length() == len ); + VERIFY( s3[len] == '\0' ); + std::basic_string s4(cs, len, std::allocator{}); + VERIFY( s4 == s3 ); + + std::basic_string> s5(cs); + VERIFY( s5 == std::basic_string_view(s1) ); + + std::basic_string> s6(cs, Alloc(6)); + VERIFY( s6 == std::basic_string_view(s1) ); + VERIFY( s6.get_allocator().personality == 6 ); + + std::basic_string> s7(cs, len, Alloc(7)); + VERIFY( s7 == std::basic_string_view(s3) ); + VERIFY( s7.get_allocator().personality == 7 ); + + return true; +} + +static_assert( test_cstr() ); + +constexpr bool +test_copy() +{ + const std::basic_string short_string = "sh"; + const std::basic_string long_string = "string longer than the SSO buffer"; + + std::basic_string s1 = short_string; + VERIFY( s1 == short_string ); + std::basic_string s2(short_string, s1.get_allocator()); + VERIFY( s2 == short_string ); + + std::basic_string s3 = long_string; + VERIFY( s3 == long_string ); + std::basic_string s4(long_string, s1.get_allocator()); + VERIFY( s4 == long_string ); + + std::basic_string> a_short_string = short_string.c_str(); + std::basic_string> a_long_string = long_string.c_str(); + + std::basic_string> s5(a_short_string); + VERIFY( s5 == a_short_string ); + std::basic_string> s6(a_short_string, s5.get_allocator()); + VERIFY( s6 == a_short_string ); + std::basic_string> s7(a_short_string, Alloc(7)); + VERIFY( s7 == a_short_string ); + VERIFY( s7.get_allocator().personality == 7 ); + + std::basic_string> s8 = a_long_string; + VERIFY( s8 == a_long_string ); + std::basic_string> s9(a_long_string, s5.get_allocator()); + VERIFY( s9 == a_long_string ); + std::basic_string> s10(a_long_string, Alloc(10)); + VERIFY( s10 == a_long_string ); + VERIFY( s10.get_allocator().personality == 10 ); + + return true; +} + +static_assert( test_copy() ); + +constexpr bool +test_move() +{ + const std::basic_string short_string = "sh"; + const std::basic_string long_string = "string longer than the SSO buffer"; + + std::basic_string s0 = short_string; + + std::basic_string s1 = std::move(s0); + VERIFY( s1 == short_string ); + std::basic_string s2(std::move(s1), std::allocator()); + VERIFY( s2 == short_string ); + + s0 = long_string; + std::basic_string s3 = std::move(s0); + VERIFY( s3 == long_string ); + std::basic_string s4(std::move(s3), s1.get_allocator()); + VERIFY( s4 == long_string ); + + std::basic_string> a_short_string = short_string.c_str(); + std::basic_string> a_long_string = long_string.c_str(); + + auto sa0 = a_short_string; + std::basic_string> s5 = std::move(sa0); + VERIFY( s5 == a_short_string ); + std::basic_string> s6(std::move(s5), sa0.get_allocator()); + VERIFY( s6 == a_short_string ); + std::basic_string> s7(std::move(s6), Alloc(7)); + VERIFY( s7 == a_short_string ); + VERIFY( s7.get_allocator().personality == 7 ); + + sa0 = a_long_string; + std::basic_string> s8 = std::move(sa0); + VERIFY( s8 == a_long_string ); + std::basic_string> s9(std::move(s8), s5.get_allocator()); + VERIFY( s9 == a_long_string ); + std::basic_string> s10(std::move(s9), Alloc(10)); + VERIFY( s10 == a_long_string ); + VERIFY( s10.get_allocator().personality == 10 ); + + return true; +} + +static_assert( test_move() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/constexpr.cc new file mode 100644 index 00000000000..3ef9862e613 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/cons/wchar_t/constexpr.cc @@ -0,0 +1,174 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } +// { dg-require-effective-target cxx11-abi } + +#include + +#ifndef __cpp_lib_constexpr_string +# error "Feature-test macro for constexpr std::string missing in " +#elif __cpp_lib_constexpr_string != 201907L +# error "Feature-test macro for constexpr std::string has wrong value in " +#endif + +#include + +using C = wchar_t; +using T = std::char_traits; + +template +struct Alloc : std::allocator +{ + using std::allocator::allocator; + + constexpr explicit Alloc(int p) : personality(p) { } + + template + constexpr Alloc(const Alloc& a) : personality(a.personality) { } + + int personality = 0; + + constexpr Alloc select_on_container_copy_construction() const + { return Alloc(-1); } + + constexpr bool operator==(const Alloc& a) const noexcept + { return personality == a.personality; } +}; + +constexpr bool +test_default_ctor() +{ + std::basic_string s0; + VERIFY( s0.empty() ); + + std::basic_string s1(std::allocator{}); + VERIFY( s1.empty() ); + + std::basic_string> s2; + VERIFY( s2.empty() ); + + std::basic_string> s3(Alloc(3)); + VERIFY( s3.empty() ); + VERIFY( s3.get_allocator().personality == 3 ); + + return true; +} + +static_assert( test_default_ctor() ); + +constexpr bool +test_cstr() +{ + const C cs[] = L"This has an embedded \0 null"; + const auto len = (sizeof(cs) - 1)/sizeof(C); + + std::basic_string s1(cs); + VERIFY( s1.length() == 21 ); + std::basic_string s2(cs, std::allocator{}); + VERIFY( s2 == s1 ); + + std::basic_string s3(cs, len); + VERIFY( s3.length() == len ); + VERIFY( s3[len] == L'\0' ); + std::basic_string s4(cs, len, std::allocator{}); + VERIFY( s4 == s3 ); + + std::basic_string> s5(cs); + VERIFY( s5 == std::basic_string_view(s1) ); + + std::basic_string> s6(cs, Alloc(6)); + VERIFY( s6 == std::basic_string_view(s1) ); + VERIFY( s6.get_allocator().personality == 6 ); + + std::basic_string> s7(cs, len, Alloc(7)); + VERIFY( s7 == std::basic_string_view(s3) ); + VERIFY( s7.get_allocator().personality == 7 ); + + return true; +} + +static_assert( test_cstr() ); + +constexpr bool +test_copy() +{ + const std::basic_string short_string = L"sh"; + const std::basic_string long_string = L"string longer than the SSO buffer"; + + std::basic_string s1 = short_string; + VERIFY( s1 == short_string ); + std::basic_string s2(short_string, s1.get_allocator()); + VERIFY( s2 == short_string ); + + std::basic_string s3 = long_string; + VERIFY( s3 == long_string ); + std::basic_string s4(long_string, s1.get_allocator()); + VERIFY( s4 == long_string ); + + std::basic_string> a_short_string = short_string.c_str(); + std::basic_string> a_long_string = long_string.c_str(); + + std::basic_string> s5(a_short_string); + VERIFY( s5 == a_short_string ); + std::basic_string> s6(a_short_string, s5.get_allocator()); + VERIFY( s6 == a_short_string ); + std::basic_string> s7(a_short_string, Alloc(7)); + VERIFY( s7 == a_short_string ); + VERIFY( s7.get_allocator().personality == 7 ); + + std::basic_string> s8 = a_long_string; + VERIFY( s8 == a_long_string ); + std::basic_string> s9(a_long_string, s5.get_allocator()); + VERIFY( s9 == a_long_string ); + std::basic_string> s10(a_long_string, Alloc(10)); + VERIFY( s10 == a_long_string ); + VERIFY( s10.get_allocator().personality == 10 ); + + return true; +} + +static_assert( test_copy() ); + +constexpr bool +test_move() +{ + const std::basic_string short_string = L"sh"; + const std::basic_string long_string = L"string longer than the SSO buffer"; + + std::basic_string s0 = short_string; + + std::basic_string s1 = std::move(s0); + VERIFY( s1 == short_string ); + std::basic_string s2(std::move(s1), std::allocator()); + VERIFY( s2 == short_string ); + + s0 = long_string; + std::basic_string s3 = std::move(s0); + VERIFY( s3 == long_string ); + std::basic_string s4(std::move(s3), s1.get_allocator()); + VERIFY( s4 == long_string ); + + std::basic_string> a_short_string = short_string.c_str(); + std::basic_string> a_long_string = long_string.c_str(); + + auto sa0 = a_short_string; + std::basic_string> s5 = std::move(sa0); + VERIFY( s5 == a_short_string ); + std::basic_string> s6(std::move(s5), sa0.get_allocator()); + VERIFY( s6 == a_short_string ); + std::basic_string> s7(std::move(s6), Alloc(7)); + VERIFY( s7 == a_short_string ); + VERIFY( s7.get_allocator().personality == 7 ); + + sa0 = a_long_string; + std::basic_string> s8 = std::move(sa0); + VERIFY( s8 == a_long_string ); + std::basic_string> s9(std::move(s8), s5.get_allocator()); + VERIFY( s9 == a_long_string ); + std::basic_string> s10(std::move(s9), Alloc(10)); + VERIFY( s10 == a_long_string ); + VERIFY( s10.get_allocator().personality == 10 ); + + return true; +} + +static_assert( test_move() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/literals/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/literals/constexpr.cc new file mode 100644 index 00000000000..27d286c85eb --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/literals/constexpr.cc @@ -0,0 +1,22 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } +// { dg-require-effective-target cxx11-abi } + +#include +#include + +constexpr bool +test_literals() +{ + using namespace std::literals; + + auto s = "narrow string"s; + auto sw = L"wide string"s; + auto s8 = u8"UTF-8 string"s; + auto su = u"UTF-16 string"s; + auto sU = U"UTF-32 string"s; + + return !s.empty() && !sw.empty() && !s8.empty() && !su.empty() && !sU.empty(); +} + +static_assert( test_literals() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/constexpr.cc new file mode 100644 index 00000000000..c875a3a19ad --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/constexpr.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } + +#include +#include + +constexpr bool +test_insert() +{ + std::string s; + s.insert(0, "one"); + VERIFY( s == "one" ); + s.insert(0, "eleventy-"); + VERIFY( s == "eleventy-one" ); + s.insert(6, "ses at ten thirteen", 15); + VERIFY( s == "elevenses at ten thirty-one" ); + + return true; +} + +static_assert( test_insert() ); + +constexpr bool +test_replace() +{ + std::string s = "abcdef"; + s.replace(2, 1, s.c_str(), 3); + VERIFY( s == "ababcdef" ); + s.replace(0, 2, "", 0); + VERIFY( s == "abcdef" ); + s.replace(1, 4, "ardwol", 6); + VERIFY( s == "aardwolf" ); + s.replace(4, 0, "vark not wolf"); + + return true; +} + +static_assert( test_replace() ); + +constexpr bool +test_erasure() +{ + std::string s = "Spiritualized Electric Mainline"; + std::erase(s, 'i'); + VERIFY( s == "Sprtualzed Electrc Manlne" ); + std::erase_if(s, [](char c) { return c == 'l'; }); + VERIFY( s == "Sprtuazed Eectrc Manne" ); + + return true; +} + +static_assert( test_erasure() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/char/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/char/constexpr.cc new file mode 100644 index 00000000000..9fd05c9b880 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/char/constexpr.cc @@ -0,0 +1,49 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } +// { dg-require-effective-target cxx11-abi } + +#include +#include + +using C = char; +using T = std::char_traits; + +constexpr bool +test_swap() +{ + std::basic_string s0; + s0.swap(s0); + VERIFY( s0.empty() ); + std::basic_string s00; + s0.swap(s00); + VERIFY( s0.empty() ); + VERIFY( s00.empty() ); + + std::basic_string s1 = "s1"; + s1.swap(s0); + VERIFY( s1.empty() ); + VERIFY( ! s0.empty() ); + s1.swap(s0); + VERIFY( s0.empty() ); + VERIFY( ! s1.empty() ); + + std::basic_string s2 = "quite a long string, but not very long"; + s2.swap(s1); + VERIFY( s2.length() == 2 ); + VERIFY( s1.length() == 38 ); + s2.swap(s1); + VERIFY( s1.length() == 2 ); + VERIFY( s2.length() == 38 ); + + swap(s2, s0); + VERIFY( s2.empty() ); + VERIFY( s0.length() == 38 ); + + auto s3 = s0; + swap(s3, s0); + VERIFY( s3 == s0 ); + + return true; +} + +static_assert( test_swap() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/wchar_t/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/wchar_t/constexpr.cc new file mode 100644 index 00000000000..4d3f188f1d6 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/swap/wchar_t/constexpr.cc @@ -0,0 +1,49 @@ +// { dg-options "-std=gnu++20" } +// { dg-do compile { target c++20 } } +// { dg-require-effective-target cxx11-abi } + +#include +#include + +using C = wchar_t; +using T = std::char_traits; + +constexpr bool +test_swap() +{ + std::basic_string s0; + s0.swap(s0); + VERIFY( s0.empty() ); + std::basic_string s00; + s0.swap(s00); + VERIFY( s0.empty() ); + VERIFY( s00.empty() ); + + std::basic_string s1 = L"s1"; + s1.swap(s0); + VERIFY( s1.empty() ); + VERIFY( ! s0.empty() ); + s1.swap(s0); + VERIFY( s0.empty() ); + VERIFY( ! s1.empty() ); + + std::basic_string s2 = L"quite a long string, but not very long"; + s2.swap(s1); + VERIFY( s2.length() == 2 ); + VERIFY( s1.length() == 38 ); + s2.swap(s1); + VERIFY( s1.length() == 2 ); + VERIFY( s2.length() == 38 ); + + swap(s2, s0); + VERIFY( s2.empty() ); + VERIFY( s0.length() == 38 ); + + auto s3 = s0; + swap(s3, s0); + VERIFY( s3 == s0 ); + + return true; +} + +static_assert( test_swap() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/version.cc b/libstdc++-v3/testsuite/21_strings/basic_string/version.cc new file mode 100644 index 00000000000..a99bb179a93 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/version.cc @@ -0,0 +1,25 @@ +// { dg-do compile { target c++17 } } + +#include + +#ifndef __cpp_lib_constexpr_string +# error "Feature-test macro for constexpr std::string missing in " +#endif + +#if __cplusplus == 201703L +# if __cpp_lib_constexpr_string != 201611L +# error "Feature-test macro for constexpr std::string has wrong value for C++17 in " +# endif +#endif + +#if __cplusplus == 202002L +# if _GLIBCXX_USE_CXX11_ABI +# if __cpp_lib_constexpr_string != 201907L +# error "Feature-test macro for constexpr std::string has wrong value for C++20 in " +# endif +# else // COW strings +# if __cpp_lib_constexpr_string != 201811L +# error "Feature-test macro for constexpr std::string has wrong value for C++20 in " +# endif +# endif +#endif -- 2.31.1