From df66af3b1edaf46420191aec73311fa408cb18c1 Mon Sep 17 00:00:00 2001 From: Daniel Kruegler Date: Mon, 4 Sep 2017 15:48:47 +0000 Subject: [PATCH] PR libstdc++/79162 implement LWG 2946 and LWG 2758 2017-09-04 Daniel Kruegler PR libstdc++/79162 Implement LWG 2946, LWG 2758's resolution missed further corrections * include/bits/basic_string.h (basic_string::compare): Add missing required noexcept specifications. (basic_string): Introduce internal _S_to_string_view and __sv_wrapper for implicit string_view conversion. (basic_string::basic_string): Fix explicit string_view conversion by implicit conversion using _S_to_string_view and __sv_wrapper. (basic_string): Introduce internal basic_string(__sv_wrapper, Alloc) constructor. (basic_string): Fix operator=(T) template by operator=(const T&) template for uncopyable types (PR 79162). (basic_string::operator+=, basic_string::append, basic_string::assign) (basic_string::insert, basic_string::replace, basic_string::find) (basic_string::rfind, basic_string::find_first_of) (basic_string::find_last_of, basic_string::find_first_not_of) (basic_string::find_last_not_of, basic_string::compare): Replace __sv_type argument by template const T& (LWG 2946) and correct documentation describing __sv_type argument. (basic_string::find, basic_string::rfind, basic_string::find_first_of) (basic_string::find_last_of, basic_string::find_first_not_of) (basic_string::find_last_not_of, basic_string::compare): Replace unconditional noexcept specification by conditional noexcept specification to partially balance the removal of noexcept by LWG 2946. * testsuite/21_strings/basic_string/79162.cc: New. * testsuite/21_strings/basic_string/lwg2946.cc: New. From-SVN: r251664 --- libstdc++-v3/ChangeLog | 29 + libstdc++-v3/include/bits/basic_string.h | 547 ++++++++++++------ .../21_strings/basic_string/79162.cc | 37 ++ .../21_strings/basic_string/lwg2946.cc | 41 ++ 4 files changed, 473 insertions(+), 181 deletions(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/79162.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ed1003a5fc4..c79888c6be5 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,32 @@ +2017-09-04 Daniel Kruegler + + PR libstdc++/79162 + Implement LWG 2946, LWG 2758's resolution missed further corrections + * include/bits/basic_string.h (basic_string::compare): Add missing + required noexcept specifications. + (basic_string): Introduce internal _S_to_string_view and __sv_wrapper + for implicit string_view conversion. + (basic_string::basic_string): Fix explicit string_view conversion by + implicit conversion using _S_to_string_view and __sv_wrapper. + (basic_string): Introduce internal basic_string(__sv_wrapper, Alloc) + constructor. + (basic_string): Fix operator=(T) template by operator=(const T&) + template for uncopyable types (PR 79162). + (basic_string::operator+=, basic_string::append, basic_string::assign) + (basic_string::insert, basic_string::replace, basic_string::find) + (basic_string::rfind, basic_string::find_first_of) + (basic_string::find_last_of, basic_string::find_first_not_of) + (basic_string::find_last_not_of, basic_string::compare): Replace + __sv_type argument by template const T& (LWG 2946) and correct + documentation describing __sv_type argument. + (basic_string::find, basic_string::rfind, basic_string::find_first_of) + (basic_string::find_last_of, basic_string::find_first_not_of) + (basic_string::find_last_not_of, basic_string::compare): Replace + unconditional noexcept specification by conditional noexcept + specification to partially balance the removal of noexcept by LWG 2946. + * testsuite/21_strings/basic_string/79162.cc: New. + * testsuite/21_strings/basic_string/lwg2946.cc: New. + 2017-08-31 Jonathan Wakely PR c++/82039 diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index a343d7b1628..0ef139b2c2b 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -117,6 +117,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 __and_, __not_>>::value, _Res>; + + // Allows an implicit conversion to __sv_type. + static __sv_type + _S_to_string_view(__sv_type __svt) noexcept + { return __svt; } + + // Wraps a string_view by explicit conversion and thus + // allows to add an internal constructor that does not + // participate in overload resolution when a string_view + // is provided. + struct __sv_wrapper + { + explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { } + __sv_type _M_sv; + }; #endif // Use empty-base optimization: http://www.cantrip.org/emptyopt.html @@ -593,7 +608,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Construct string from a substring of a string_view. - * @param __t Source string view. + * @param __t Source object convertible to string view. * @param __pos The index of the first character to copy from __t. * @param __n The number of characters to copy from __t. * @param __a Allocator to use. @@ -601,16 +616,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 template> basic_string(const _Tp& __t, size_type __pos, size_type __n, const _Alloc& __a = _Alloc()) - : basic_string(__sv_type(__t).substr(__pos, __n), __a) { } + : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { } /** * @brief Construct string from a string_view. - * @param __sv Source string view. + * @param __t Source object convertible to string view. * @param __a Allocator to use (default is default allocator). */ + template> + explicit + basic_string(const _Tp& __t, const _Alloc& __a = _Alloc()) + : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { } + + /** + * @brief Only internally used: Construct string from a string view + * wrapper. + * @param __svw string view wrapper. + * @param __a Allocator to use. + */ explicit - basic_string(__sv_type __sv, const _Alloc& __a = _Alloc()) - : basic_string(__sv.data(), __sv.size(), __a) { } + basic_string(__sv_wrapper __svw, const _Alloc& __a) + : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { } #endif // C++17 /** @@ -756,19 +782,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Set value to string constructed from a string_view. - * @param __sv A string_view. + * @param __svt An object convertible to string_view. */ - template - _If_sv<_Tp, basic_string&> - operator=(_Tp __sv) - { return this->assign(__sv); } + template + _If_sv<_Tp, basic_string&> + operator=(const _Tp& __svt) + { return this->assign(__svt); } /** * @brief Convert to a string_view. * @return A string_view. */ operator __sv_type() const noexcept - { return __sv_type(data(), size()); } + { return __sv_type(data(), size()); } #endif // C++17 // Iterators: @@ -1157,12 +1183,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Append a string_view. - * @param __sv The string_view to be appended. + * @param __svt An object convertible to string_view to be appended. * @return Reference to this string. */ - basic_string& - operator+=(__sv_type __sv) - { return this->append(__sv); } + template + _If_sv<_Tp, basic_string&> + operator+=(const _Tp& __svt) + { return this->append(__svt); } #endif // C++17 /** @@ -1265,22 +1292,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Append a string_view. - * @param __sv The string_view to be appended. + * @param __svt An object convertible to string_view to be appended. * @return Reference to this string. */ - basic_string& - append(__sv_type __sv) - { return this->append(__sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->append(__sv.data(), __sv.size()); + } /** * @brief Append a range of characters from a string_view. - * @param __sv The string_view to be appended from. + * @param __svt An object convertible to string_view to be appended from. * @param __pos The position in the string_view to append from. * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - template - _If_sv<_Tp, basic_string&> + template + _If_sv<_Tp, basic_string&> append(const _Tp& __svt, size_type __pos, size_type __n = npos) { __sv_type __sv = __svt; @@ -1433,21 +1464,25 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Set value from a string_view. - * @param __sv The source string_view. + * @param __svt The source object convertible to string_view. * @return Reference to this string. */ - basic_string& - assign(__sv_type __sv) - { return this->assign(__sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->assign(__sv.data(), __sv.size()); + } /** * @brief Set value from a range of characters in a string_view. - * @param __sv The source string_view. + * @param __svt The source object convertible to string_view. * @param __pos The position in the string_view to assign from. * @param __n The number of characters to assign. * @return Reference to this string. */ - template + template _If_sv<_Tp, basic_string&> assign(const _Tp& __svt, size_type __pos, size_type __n = npos) { @@ -1692,23 +1727,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 /** * @brief Insert a string_view. * @param __pos Iterator referencing position in string to insert at. - * @param __sv The string_view to insert. + * @param __svt The object convertible to string_view to insert. * @return Reference to this string. */ - basic_string& - insert(size_type __pos, __sv_type __sv) - { return this->insert(__pos, __sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + insert(size_type __pos, const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->insert(__pos, __sv.data(), __sv.size()); + } /** * @brief Insert a string_view. * @param __pos Iterator referencing position in string to insert at. - * @param __sv The string_view to insert from. + * @param __svt The object convertible to string_view to insert from. * @param __pos Iterator referencing position in string_view to insert * from. * @param __n The number of characters to insert. * @return Reference to this string. */ - template + template _If_sv<_Tp, basic_string&> insert(size_type __pos1, const _Tp& __svt, size_type __pos2, size_type __n = npos) @@ -2120,23 +2159,27 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Replace range of characters with string_view. * @param __pos The position to replace at. * @param __n The number of characters to replace. - * @param __sv The string_view to insert. + * @param __svt The object convertible to string_view to insert. * @return Reference to this string. */ - basic_string& - replace(size_type __pos, size_type __n, __sv_type __sv) - { return this->replace(__pos, __n, __sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + replace(size_type __pos, size_type __n, const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->replace(__pos, __n, __sv.data(), __sv.size()); + } /** * @brief Replace range of characters with string_view. * @param __pos1 The position to replace at. * @param __n1 The number of characters to replace. - * @param __sv The string_view to insert from. + * @param __svt The object convertible to string_view to insert from. * @param __pos2 The position in the string_view to insert from. * @param __n2 The number of characters to insert. * @return Reference to this string. */ - template + template _If_sv<_Tp, basic_string&> replace(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) @@ -2153,12 +2196,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 to replace at. * @param __i2 An iterator referencing the end position for the replace. - * @param __sv The string_view to insert from. + * @param __svt The object convertible to string_view to insert from. * @return Reference to this string. */ - basic_string& - replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) - { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } + template + _If_sv<_Tp, basic_string&> + replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->replace(__i1 - begin(), __i2 - __i1, __sv); + } #endif // C++17 private: @@ -2288,13 +2335,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find position of a string_view. - * @param __sv The string_view to locate. + * @param __svt The object convertible to string_view to locate. * @param __pos Index of character to search from (default 0). * @return Index of start of first occurrence. */ - size_type - find(__sv_type __sv, size_type __pos = 0) const noexcept - { return this->find(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find(const _Tp& __svt, size_type __pos = 0) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -2345,13 +2397,18 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find last position of a string_view. - * @param __sv The string_view to locate. + * @param __svt The object convertible to string_view to locate. * @param __pos Index of character to search back from (default end). * @return Index of start of last occurrence. */ - size_type - rfind(__sv_type __sv, size_type __pos = npos) const noexcept - { return this->rfind(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + rfind(const _Tp& __svt, size_type __pos = npos) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->rfind(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -2419,13 +2476,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find position of a character of a string_view. - * @param __sv A string_view containing characters to locate. + * @param __svt An object convertible to string_view containing + * characters to locate. * @param __pos Index of character to search from (default 0). * @return Index of first occurrence. */ - size_type - find_first_of(__sv_type __sv, size_type __pos = 0) const noexcept - { return this->find_first_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_first_of(const _Tp& __svt, size_type __pos = 0) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_first_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -2497,13 +2560,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find last position of a character of string. - * @param __sv A string_view containing characters to locate. + * @param __svt An object convertible to string_view containing + * characters to locate. * @param __pos Index of character to search back from (default end). * @return Index of last occurrence. */ - size_type - find_last_of(__sv_type __sv, size_type __pos = npos) const noexcept - { return this->find_last_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_last_of(const _Tp& __svt, size_type __pos = npos) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_last_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -2574,13 +2643,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find position of a character not in a string_view. - * @param __sv A string_view containing characters to avoid. + * @param __svt A object convertible to string_view containing + * characters to avoid. * @param __pos Index of character to search from (default 0). * @return Index of first occurrence. */ - size_type - find_first_not_of(__sv_type __sv, size_type __pos = 0) const noexcept - { return this->find_first_not_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_first_not_of(const _Tp& __svt, size_type __pos = 0) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_first_not_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -2650,13 +2725,19 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find last position of a character not in a string_view. - * @param __sv A string_view containing characters to avoid. + * @param __svt An object convertible to string_view containing + * characters to avoid. * @param __pos Index of character to search back from (default end). * @return Index of last occurrence. */ - size_type - find_last_not_of(__sv_type __sv, size_type __pos = npos) const noexcept - { return this->find_last_not_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_last_not_of(const _Tp& __svt, size_type __pos = npos) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_last_not_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -2754,46 +2835,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Compare to a string_view. - * @param __sv A string_view to compare against. + * @param __svt An object convertible to string_view to compare against. * @return Integer < 0, 0, or > 0. */ - int - compare(__sv_type __sv) const - { - const size_type __size = this->size(); - const size_type __osize = __sv.size(); - const size_type __len = std::min(__size, __osize); - - int __r = traits_type::compare(_M_data(), __sv.data(), __len); - if (!__r) - __r = _S_compare(__size, __osize); - return __r; - } + template + _If_sv<_Tp, int> + compare(const _Tp& __svt) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + const size_type __size = this->size(); + const size_type __osize = __sv.size(); + const size_type __len = std::min(__size, __osize); + + int __r = traits_type::compare(_M_data(), __sv.data(), __len); + if (!__r) + __r = _S_compare(__size, __osize); + return __r; + } /** * @brief Compare to a string_view. * @param __pos A position in the string to start comparing from. * @param __n The number of characters to compare. - * @param __sv A string_view to compare against. + * @param __svt An object convertible to string_view to compare + * against. * @return Integer < 0, 0, or > 0. */ - int - compare(size_type __pos, size_type __n, __sv_type __sv) const - { return __sv_type(*this).substr(__pos, __n).compare(__sv); } + template + _If_sv<_Tp, int> + compare(size_type __pos, size_type __n, const _Tp& __svt) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return __sv_type(*this).substr(__pos, __n).compare(__sv); + } /** * @brief Compare to a string_view. * @param __pos1 A position in the string to start comparing from. * @param __n1 The number of characters to compare. - * @param __sv A string_view to compare against. + * @param __svt An object convertible to string_view to compare + * against. * @param __pos2 A position in the string_view to start comparing from. * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ - template + template _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const + noexcept(is_same<_Tp, __sv_type>::value) { __sv_type __sv = __svt; return __sv_type(*this) @@ -3348,6 +3440,21 @@ _GLIBCXX_END_NAMESPACE_CXX11 __and_, __not_>>::value, _Res>; + + // Allows an implicit conversion to __sv_type. + static __sv_type + _S_to_string_view(__sv_type __svt) noexcept + { return __svt; } + + // Wraps a string_view by explicit conversion and thus + // allows to add an internal constructor that does not + // participate in overload resolution when a string_view + // is provided. + struct __sv_wrapper + { + explicit __sv_wrapper(__sv_type __sv) noexcept : _M_sv(__sv) { } + __sv_type _M_sv; + }; #endif public: @@ -3474,7 +3581,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Construct string from a substring of a string_view. - * @param __t Source string view. + * @param __t Source object convertible to string view. * @param __pos The index of the first character to copy from __t. * @param __n The number of characters to copy from __t. * @param __a Allocator to use. @@ -3482,16 +3589,27 @@ _GLIBCXX_END_NAMESPACE_CXX11 template> basic_string(const _Tp& __t, size_type __pos, size_type __n, const _Alloc& __a = _Alloc()) - : basic_string(__sv_type(__t).substr(__pos, __n), __a) { } + : basic_string(_S_to_string_view(__t).substr(__pos, __n), __a) { } /** * @brief Construct string from a string_view. - * @param __sv Source string view. + * @param __t Source object convertible to string view. * @param __a Allocator to use (default is default allocator). */ + template> + explicit + basic_string(const _Tp& __t, const _Alloc& __a = _Alloc()) + : basic_string(__sv_wrapper(_S_to_string_view(__t)), __a) { } + + /** + * @brief Only internally used: Construct string from a string view + * wrapper. + * @param __svw string view wrapper. + * @param __a Allocator to use. + */ explicit - basic_string(__sv_type __sv, const _Alloc& __a = _Alloc()) - : basic_string(__sv.data(), __sv.size(), __a) { } + basic_string(__sv_wrapper __svw, const _Alloc& __a) + : basic_string(__svw._M_sv.data(), __svw._M_sv.size(), __a) { } #endif // C++17 /** @@ -3562,12 +3680,12 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Set value to string constructed from a string_view. - * @param __sv A string_view. + * @param __svt An object convertible to string_view. */ template _If_sv<_Tp, basic_string&> - operator=(_Tp __sv) - { return this->assign(__sv); } + operator=(const _Tp& __svt) + { return this->assign(__svt); } /** * @brief Convert to a string_view. @@ -3984,12 +4102,13 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Append a string_view. - * @param __sv The string_view to be appended. + * @param __svt The object convertible to string_view to be appended. * @return Reference to this string. */ - basic_string& - operator+=(__sv_type __sv) - { return this->append(__sv); } + template + _If_sv<_Tp, basic_string&> + operator+=(const _Tp& __svt) + { return this->append(__svt); } #endif // C++17 /** @@ -4075,22 +4194,27 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Append a string_view. - * @param __sv The string_view to be appended. + * @param __svt The object convertible to string_view to be appended. * @return Reference to this string. */ - basic_string& - append(__sv_type __sv) - { return this->append(__sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->append(__sv.data(), __sv.size()); + } /** * @brief Append a range of characters from a string_view. - * @param __sv The string_view to be appended from. + * @param __svt The object convertible to string_view to be appended + * from. * @param __pos The position in the string_view to append from. * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - template - _If_sv<_Tp, basic_string&> + template + _If_sv<_Tp, basic_string&> append(const _Tp& __svt, size_type __pos, size_type __n = npos) { __sv_type __sv = __svt; @@ -4228,23 +4352,27 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Set value from a string_view. - * @param __sv The source string_view. + * @param __svt The source object convertible to string_view. * @return Reference to this string. */ - basic_string& - assign(__sv_type __sv) - { return this->assign(__sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->assign(__sv.data(), __sv.size()); + } /** * @brief Set value from a range of characters in a string_view. - * @param __sv The source string_view. + * @param __svt The source object convertible to string_view. * @param __pos The position in the string_view to assign from. * @param __n The number of characters to assign. * @return Reference to this string. */ - template - _If_sv<_Tp, basic_string&> - assign(const _Tp& __svt, size_type __pos, size_type __n = npos) + template + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) { __sv_type __sv = __svt; return assign(__sv.data() @@ -4432,25 +4560,29 @@ _GLIBCXX_END_NAMESPACE_CXX11 /** * @brief Insert a string_view. * @param __pos Iterator referencing position in string to insert at. - * @param __sv The string_view to insert. + * @param __svt The object convertible to string_view to insert. * @return Reference to this string. */ - basic_string& - insert(size_type __pos, __sv_type __sv) - { return this->insert(__pos, __sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + insert(size_type __pos, const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->insert(__pos, __sv.data(), __sv.size()); + } /** * @brief Insert a string_view. * @param __pos Iterator referencing position in string to insert at. - * @param __sv The string_view to insert from. + * @param __svt The object convertible to string_view to insert from. * @param __pos Iterator referencing position in string_view to insert * from. * @param __n The number of characters to insert. * @return Reference to this string. */ - template - _If_sv<_Tp, basic_string&> - insert(size_type __pos1, const _Tp& __svt, + template + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, size_type __pos2, size_type __n = npos) { __sv_type __sv = __svt; @@ -4793,7 +4925,7 @@ _GLIBCXX_END_NAMESPACE_CXX11 return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __k1.base(), __k2 - __k1); } - + #if __cplusplus >= 201103L /** * @brief Replace range of characters with initializer_list. @@ -4819,31 +4951,35 @@ _GLIBCXX_END_NAMESPACE_CXX11 * @brief Replace range of characters with string_view. * @param __pos The position to replace at. * @param __n The number of characters to replace. - * @param __sv The string_view to insert. + * @param __svt The object convertible to string_view to insert. * @return Reference to this string. */ - basic_string& - replace(size_type __pos, size_type __n, __sv_type __sv) - { return this->replace(__pos, __n, __sv.data(), __sv.size()); } + template + _If_sv<_Tp, basic_string&> + replace(size_type __pos, size_type __n, const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->replace(__pos, __n, __sv.data(), __sv.size()); + } /** * @brief Replace range of characters with string_view. * @param __pos1 The position to replace at. * @param __n1 The number of characters to replace. - * @param __sv The string_view to insert from. + * @param __svt The object convertible to string_view to insert from. * @param __pos2 The position in the string_view to insert from. * @param __n2 The number of characters to insert. * @return Reference to this string. */ - template - _If_sv<_Tp, basic_string&> - replace(size_type __pos1, size_type __n1, const _Tp& __svt, + template + _If_sv<_Tp, basic_string&> + replace(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) { __sv_type __sv = __svt; - return this->replace(__pos1, __n1, __sv.data() - + __sv._M_check(__pos2, "basic_string::replace"), - __sv._M_limit(__pos2, __n2)); + return this->replace(__pos1, __n1, + __sv.data() + __sv._M_check(__pos2, "basic_string::replace"), + __sv._M_limit(__pos2, __n2)); } /** @@ -4852,12 +4988,16 @@ _GLIBCXX_END_NAMESPACE_CXX11 to replace at. * @param __i2 An iterator referencing the end position for the replace. - * @param __sv The string_view to insert from. + * @param __svt The object convertible to string_view to insert from. * @return Reference to this string. */ - basic_string& - replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) - { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } + template + _If_sv<_Tp, basic_string&> + replace(const_iterator __i1, const_iterator __i2, const _Tp& __svt) + { + __sv_type __sv = __svt; + return this->replace(__i1 - begin(), __i2 - __i1, __sv); + } #endif // C++17 private: @@ -5062,13 +5202,18 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find position of a string_view. - * @param __sv The string_view to locate. + * @param __svt The object convertible to string_view to locate. * @param __pos Index of character to search from (default 0). * @return Index of start of first occurrence. */ - size_type - find(__sv_type __sv, size_type __pos = 0) const noexcept - { return this->find(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find(const _Tp& __svt, size_type __pos = 0) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -5135,13 +5280,18 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find last position of a string_view. - * @param __sv The string_view to locate. + * @param __svt The object convertible to string_view to locate. * @param __pos Index of character to search back from (default end). * @return Index of start of last occurrence. */ - size_type - rfind(__sv_type __sv, size_type __pos = npos) const noexcept - { return this->rfind(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + rfind(const _Tp& __svt, size_type __pos = npos) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->rfind(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -5213,13 +5363,19 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find position of a character of a string_view. - * @param __sv A string_view containing characters to locate. + * @param __svt An object convertible to string_view containing + * characters to locate. * @param __pos Index of character to search from (default 0). * @return Index of first occurrence. */ - size_type - find_first_of(__sv_type __sv, size_type __pos = 0) const noexcept - { return this->find_first_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_first_of(const _Tp& __svt, size_type __pos = 0) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_first_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -5291,13 +5447,19 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find last position of a character of string. - * @param __sv A string_view containing characters to locate. + * @param __svt An object convertible to string_view containing + * characters to locate. * @param __pos Index of character to search back from (default end). * @return Index of last occurrence. */ - size_type - find_last_of(__sv_type __sv, size_type __pos = npos) const noexcept - { return this->find_last_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_last_of(const _Tp& __svt, size_type __pos = npos) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_last_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -5366,13 +5528,19 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find position of a character not in a string_view. - * @param __sv A string_view containing characters to avoid. + * @param __svt An object convertible to string_view containing + * characters to avoid. * @param __pos Index of character to search from (default 0). * @return Index of first occurrence. */ - size_type - find_first_not_of(__sv_type __sv, size_type __pos = 0) const noexcept - { return this->find_first_not_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_first_not_of(const _Tp& __svt, size_type __pos = 0) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_first_not_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -5442,13 +5610,19 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Find last position of a character not in a string_view. - * @param __sv A string_view containing characters to avoid. + * @param __svt An object convertible to string_view containing + * characters to avoid. * @param __pos Index of character to search back from (default end). * @return Index of last occurrence. */ - size_type - find_last_not_of(__sv_type __sv, size_type __pos = npos) const noexcept - { return this->find_last_not_of(__sv.data(), __pos, __sv.size()); } + template + _If_sv<_Tp, size_type> + find_last_not_of(const _Tp& __svt, size_type __pos = npos) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return this->find_last_not_of(__sv.data(), __pos, __sv.size()); + } #endif // C++17 /** @@ -5498,46 +5672,57 @@ _GLIBCXX_END_NAMESPACE_CXX11 #if __cplusplus > 201402L /** * @brief Compare to a string_view. - * @param __sv A string_view to compare against. + * @param __svt An object convertible to string_view to compare against. * @return Integer < 0, 0, or > 0. */ - int - compare(__sv_type __sv) const - { - const size_type __size = this->size(); - const size_type __osize = __sv.size(); - const size_type __len = std::min(__size, __osize); - - int __r = traits_type::compare(_M_data(), __sv.data(), __len); - if (!__r) - __r = _S_compare(__size, __osize); - return __r; - } + template + _If_sv<_Tp, int> + compare(const _Tp& __svt) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + const size_type __size = this->size(); + const size_type __osize = __sv.size(); + const size_type __len = std::min(__size, __osize); + + int __r = traits_type::compare(_M_data(), __sv.data(), __len); + if (!__r) + __r = _S_compare(__size, __osize); + return __r; + } /** * @brief Compare to a string_view. * @param __pos A position in the string to start comparing from. * @param __n The number of characters to compare. - * @param __sv A string_view to compare against. + * @param __svt An object convertible to string_view to compare + * against. * @return Integer < 0, 0, or > 0. */ - int - compare(size_type __pos, size_type __n, __sv_type __sv) const - { return __sv_type(*this).substr(__pos, __n).compare(__sv); } + template + _If_sv<_Tp, int> + compare(size_type __pos, size_type __n, const _Tp& __svt) const + noexcept(is_same<_Tp, __sv_type>::value) + { + __sv_type __sv = __svt; + return __sv_type(*this).substr(__pos, __n).compare(__sv); + } /** * @brief Compare to a string_view. * @param __pos1 A position in the string to start comparing from. * @param __n1 The number of characters to compare. - * @param __sv A string_view to compare against. + * @param __svt An object convertible to string_view to compare + * against. * @param __pos2 A position in the string_view to start comparing from. * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ - template + template _If_sv<_Tp, int> compare(size_type __pos1, size_type __n1, const _Tp& __svt, size_type __pos2, size_type __n2 = npos) const + noexcept(is_same<_Tp, __sv_type>::value) { __sv_type __sv = __svt; return __sv_type(*this) diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/79162.cc b/libstdc++-v3/testsuite/21_strings/basic_string/79162.cc new file mode 100644 index 00000000000..42a046f9e54 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/79162.cc @@ -0,0 +1,37 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +template +class opt : public DataType +{ + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; +public: + opt() {} +}; + +int main() +{ + opt PGOTestProfileFile; + std::string ProfileFileName; + ProfileFileName = PGOTestProfileFile; +} diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc new file mode 100644 index 00000000000..74d5a5c89a7 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string/lwg2946.cc @@ -0,0 +1,41 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2017 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +int main() +{ + std::string s({"abc", 1}); + s = {"abc", 1}; + s += {"abc", 1}; + s.append({"abc", 1}); + s.assign({"abc", 1}); + s.insert(0, {"abc", 1}); + s.replace(0, 1, {"abc", 1}); + s.replace(s.cbegin(), s.cbegin(), {"abc", 1}); + s.find({"abc", 1}); + s.rfind({"abc", 1}); + s.find_first_of({"abc", 1}); + s.find_last_of({"abc", 1}); + s.find_first_not_of({"abc", 1}); + s.find_last_not_of({"abc", 1}); + s.compare({"abc", 1}); + s.compare(0, 1, {"abc", 1}); +} -- 2.30.2