commit 80e14013c4581fba08099f7a627c63cebc2a378e Author: Jonathan Wakely Date: Tue Aug 16 13:50:55 2016 +0100 PR 77264 constrain new std::basic_string overloads PR libstdc++/77264 * include/bits/basic_string.h (operator=(__sv_type) (append(__sv_type), assign(__sv_type), insert(size_type, __sv_type)) (replace(size_type, size_type, __sv_type)) (replace(const_iterator, const_iterator, __sv_type)) (find(__sv_type, size_type), rfind(__sv_type, size_type)) (compare(size_type, size_type, __sv_type)): Reformat. (_If_sv): Define helper for SFINAE constaints. (append(const _Tp&, size_type, size_type)) (assign(const _Tp&, size_type, size_type)) (insert(size_type, const _Tp&, size_type, size_type)) (replace(size_type, size_type, const _Tp&, size_type, size_type)): Use _If_sv. * testsuite/21_strings/basic_string/modifiers/replace/char/7.cc: Test SFINAE constraints. * testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc: Likewise. diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h index 89e2100..68cfc99 100644 --- a/libstdc++-v3/include/bits/basic_string.h +++ b/libstdc++-v3/include/bits/basic_string.h @@ -709,7 +709,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @brief Set value to string constructed from a string_view. * @param __sv A string_view. */ - basic_string& operator=(__sv_type __sv) + basic_string& + operator=(__sv_type __sv) { return this->assign(__sv); } /** @@ -1217,9 +1218,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to be appended. * @return Reference to this string. */ - basic_string& append(__sv_type __sv) + basic_string& + append(__sv_type __sv) { return this->append(__sv.data(), __sv.size()); } + template + using _If_sv = enable_if_t< + __and_, + __not_>>::value, + _Res>; + /** * @brief Append a range of characters from a string_view. * @param __sv The string_view to be appended from. @@ -1227,17 +1235,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to append from the string_view. * @return Reference to this string. */ - template , - bool> = true> - basic_string& append(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_append(__sv.data() - + __sv._M_check(__pos, "basic_string::append"), - __sv._M_limit(__pos, __n)); - } + template + _If_sv<_Tp, basic_string&> + append(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_append(__sv.data() + + __sv._M_check(__pos, "basic_string::append"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 /** @@ -1386,7 +1392,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The source string_view. * @return Reference to this string. */ - basic_string& assign(__sv_type __sv) + basic_string& + assign(__sv_type __sv) { return this->assign(__sv.data(), __sv.size()); } /** @@ -1396,18 +1403,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to assign. * @return Reference to this string. */ - template , - bool> = true> - basic_string& - assign(const _Tp& __svt, - size_type __pos, size_type __n = npos) - { - __sv_type __sv = __svt; - return _M_replace(size_type(0), this->size(), __sv.data() - + __sv._M_check(__pos, "basic_string::assign"), - __sv._M_limit(__pos, __n)); - } + template + _If_sv<_Tp, basic_string&> + assign(const _Tp& __svt, size_type __pos, size_type __n = npos) + { + __sv_type __sv = __svt; + return _M_replace(size_type(0), this->size(), __sv.data() + + __sv._M_check(__pos, "basic_string::assign"), + __sv._M_limit(__pos, __n)); + } #endif // C++17 #if __cplusplus >= 201103L @@ -1647,8 +1651,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& insert(size_type __pos, - __sv_type __sv) + basic_string& + insert(size_type __pos, __sv_type __sv) { return this->insert(__pos, __sv.data(), __sv.size()); } /** @@ -1660,17 +1664,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n The number of characters to insert. * @return Reference to this string. */ - template , - bool> = true> - basic_string& insert(size_type __pos1, const _Tp& __svt, - size_type __pos2, size_type __n = npos) - { - __sv_type __sv = __svt; - return this->replace(__pos1, size_type(0), __sv.data() - + __sv._M_check(__pos2, "basic_string::insert"), - __sv._M_limit(__pos2, __n)); - } + template + _If_sv<_Tp, basic_string&> + insert(size_type __pos1, const _Tp& __svt, + size_type __pos2, size_type __n = npos) + { + __sv_type __sv = __svt; + return this->replace(__pos1, size_type(0), __sv.data() + + __sv._M_check(__pos2, "basic_string::insert"), + __sv._M_limit(__pos2, __n)); + } #endif // C++17 /** @@ -2070,8 +2073,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert. * @return Reference to this string. */ - basic_string& replace(size_type __pos, size_type __n, - __sv_type __sv) + basic_string& + replace(size_type __pos, size_type __n, __sv_type __sv) { return this->replace(__pos, __n, __sv.data(), __sv.size()); } /** @@ -2083,18 +2086,16 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to insert. * @return Reference to this string. */ - template , - bool> = true> - 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)); - } + 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)); + } /** * @brief Replace range of characters with string_view. @@ -2105,8 +2106,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __sv The string_view to insert from. * @return Reference to this string. */ - basic_string& replace(const_iterator __i1, const_iterator __i2, - __sv_type __sv) + basic_string& + replace(const_iterator __i1, const_iterator __i2, __sv_type __sv) { return this->replace(__i1 - begin(), __i2 - __i1, __sv); } #endif // C++17 @@ -2241,8 +2242,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of first occurrence. */ size_type - find(__sv_type __sv, - size_type __pos = 0) const noexcept + find(__sv_type __sv, size_type __pos = 0) const noexcept { return this->find(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2299,8 +2299,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @return Index of start of last occurrence. */ size_type - rfind (__sv_type __sv, - size_type __pos = npos) const noexcept + rfind(__sv_type __sv, size_type __pos = npos) const noexcept { return this->rfind(__sv.data(), __pos, __sv.size()); } #endif // C++17 @@ -2721,11 +2720,8 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @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); - } + compare(size_type __pos, size_type __n, __sv_type __sv) const + { return __sv_type(*this).substr(__pos, __n).compare(__sv); } /** * @brief Compare to a string_view. @@ -2736,17 +2732,15 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 * @param __n2 The number of characters to compare. * @return Integer < 0, 0, or > 0. */ - template , - bool> = true> - int compare(size_type __pos1, size_type __n1, - const _Tp& __svt, - size_type __pos2, size_type __n2 = npos) const - { - __sv_type __sv = __svt; - return __sv_type(*this) - .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); - } + template + _If_sv<_Tp, int> + compare(size_type __pos1, size_type __n1, const _Tp& __svt, + size_type __pos2, size_type __n2 = npos) const + { + __sv_type __sv = __svt; + return __sv_type(*this) + .substr(__pos1, __n1).compare(__sv.substr(__pos2, __n2)); + } #endif // C++17 /** diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc index 004b235..2a2858b 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/char/7.cc @@ -47,8 +47,30 @@ test03() VERIFY (str2 == "foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::string str("a"); + char c = 'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == 'b'); + + struct S { + operator char*() { return &c; } + operator std::string_view() { return "!"; } + char c = 'a'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == 'a'); +} + int main() { test03(); + test04(); return 0; } diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc index 88d2666..1e2505e 100644 --- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc +++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/replace/wchar_t/7.cc @@ -47,8 +47,30 @@ test03() VERIFY (str2 == L"foofoo"); } +// PR libstdc++/77264 +void +test04() +{ + bool test __attribute__((unused)) = true; + + std::wstring str(L"a"); + wchar_t c = L'b'; + str.replace(0, 1, &c, 1); + VERIFY (str[0] == L'b'); + + struct S { + operator wchar_t*() { return &c; } + operator std::wstring_view() { return L"!"; } + wchar_t c = L'a'; + }; + + str.replace(0, 1, S{}, 1); + VERIFY (str[0] == L'a'); +} + int main() { test03(); + test04(); return 0; }