[gcc r17-2095] libstdc++: implement LWG3662 basic_string::append/assign(NTBS, pos, n) suboptimal
Yuao Ma
yuao@gcc.gnu.org
Thu Jul 2 15:55:20 GMT 2026
https://gcc.gnu.org/g:7084db3f6e1cc68b422fdff81c823861d19c01ed
commit r17-2095-g7084db3f6e1cc68b422fdff81c823861d19c01ed
Author: Yuao Ma <c8ef@outlook.com>
Date: Thu Jul 2 20:32:17 2026 +0800
libstdc++: implement LWG3662 basic_string::append/assign(NTBS, pos, n) suboptimal
This patch implements LWG3662 for both ABIs of strings.
libstdc++-v3/ChangeLog:
* include/bits/basic_string.h(append, assign): Add new
overloads.
* include/bits/cow_string.h(append, assign): Ditto.
* testsuite/21_strings/basic_string/modifiers/append/char/2.cc:
Test new overloads.
* testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc:
Ditto.
* testsuite/21_strings/basic_string/modifiers/assign/char/3.cc:
Ditto.
* testsuite/21_strings/basic_string/modifiers/assign/wchar_t/3.cc:
Ditto.
Diff:
---
libstdc++-v3/include/bits/basic_string.h | 28 ++++++++++++++++++++++
libstdc++-v3/include/bits/cow_string.h | 26 ++++++++++++++++++++
.../basic_string/modifiers/append/char/2.cc | 16 +++++++++++++
.../basic_string/modifiers/append/wchar_t/2.cc | 16 +++++++++++++
.../basic_string/modifiers/assign/char/3.cc | 16 +++++++++++++
.../basic_string/modifiers/assign/wchar_t/3.cc | 16 +++++++++++++
6 files changed, 118 insertions(+)
diff --git a/libstdc++-v3/include/bits/basic_string.h b/libstdc++-v3/include/bits/basic_string.h
index 65d92ebfbcf8..fd9419220a49 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1767,6 +1767,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
+ std::__sv_check(__sv.size(), __pos, "basic_string::append"),
std::__sv_limit(__sv.size(), __pos, __n));
}
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3662. basic_string::append/assign(NTBS, pos, n) suboptimal
+ /**
+ * @brief Append a C substring.
+ * @param __s The C string to append.
+ * @param __pos The position in the C string to append from.
+ * @param __n The number of characters to append.
+ * @return Reference to this string.
+ */
+ _GLIBCXX20_CONSTEXPR
+ basic_string&
+ append(const _CharT* __s, size_type __pos, size_type __n)
+ { return append(__sv_type(__s).substr(__pos, __n)); }
#endif // C++17
/**
@@ -2040,6 +2054,20 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
+ std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
std::__sv_limit(__sv.size(), __pos, __n));
}
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3662. basic_string::append/assign(NTBS, pos, n) suboptimal
+ /**
+ * @brief Set value to a C substring.
+ * @param __s The C string to use.
+ * @param __pos The position in the C string to assign from.
+ * @param __n Number of characters to use.
+ * @return Reference to this string.
+ */
+ _GLIBCXX20_CONSTEXPR
+ basic_string&
+ assign(const _CharT* __s, size_type __pos, size_type __n)
+ { return assign(__sv_type(__s).substr(__pos, __n)); }
#endif // C++17
#if __cplusplus >= 201103L
diff --git a/libstdc++-v3/include/bits/cow_string.h b/libstdc++-v3/include/bits/cow_string.h
index 7c945f6b9983..0f1a2e082d0a 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -1427,6 +1427,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ std::__sv_check(__sv.size(), __pos, "basic_string::append"),
std::__sv_limit(__sv.size(), __pos, __n));
}
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3662. basic_string::append/assign(NTBS, pos, n) suboptimal
+ /**
+ * @brief Append a C substring.
+ * @param __s The C string to append.
+ * @param __pos The position in the C string to append from.
+ * @param __n The number of characters to append.
+ * @return Reference to this string.
+ */
+ basic_string&
+ append(const _CharT* __s, size_type __pos, size_type __n)
+ { return append(__sv_type(__s).substr(__pos, __n)); }
#endif // C++17
/**
@@ -1600,6 +1613,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
+ std::__sv_check(__sv.size(), __pos, "basic_string::assign"),
std::__sv_limit(__sv.size(), __pos, __n));
}
+
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 3662. basic_string::append/assign(NTBS, pos, n) suboptimal
+ /**
+ * @brief Set value to a C substring.
+ * @param __s The C string to use.
+ * @param __pos The position in the C string to assign from.
+ * @param __n Number of characters to use.
+ * @return Reference to this string.
+ */
+ basic_string&
+ assign(const _CharT* __s, size_type __pos, size_type __n)
+ { return assign(__sv_type(__s).substr(__pos, __n)); }
#endif // C++17
/**
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/2.cc
index d70fc190b454..d9ccbd768960 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/2.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/char/2.cc
@@ -19,11 +19,13 @@
// 21.3.5 string modifiers
+#include <stdexcept>
#include <string>
#include <testsuite_hooks.h>
// append(const _CharT* __s, size_type __n)
// append(const _CharT* __s)
+// append(const _CharT* __s, size_type __pos, size_type __n)
void
test02()
{
@@ -55,6 +57,20 @@ test02()
two.append(two.c_str(), 3);
VERIFY( two == "Written in your eyeseyesWri" );
+
+ two.append(two.c_str(), 8, 2);
+ VERIFY( two == "Written in your eyeseyesWriin" );
+
+ try {
+ two.append("a\0b", 2, 1);
+ VERIFY( false );
+ }
+ catch(std::out_of_range& fail) {
+ VERIFY( true );
+ }
+ catch(...) {
+ VERIFY( false );
+ }
}
int main()
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc
index 1922874de7f2..d0d95fb3f27b 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/append/wchar_t/2.cc
@@ -19,11 +19,13 @@
// 21.3.5 string modifiers
+#include <stdexcept>
#include <string>
#include <testsuite_hooks.h>
// append(const _CharT* __s, size_type __n)
// append(const _CharT* __s)
+// append(const _CharT* __s, size_type __pos, size_type __n)
void
test02()
{
@@ -55,6 +57,20 @@ test02()
two.append(two.c_str(), 3);
VERIFY( two == L"Written in your eyeseyesWri" );
+
+ two.append(two.c_str(), 8, 2);
+ VERIFY( two == L"Written in your eyeseyesWriin" );
+
+ try {
+ two.append(L"a\0b", 2, 1);
+ VERIFY( false );
+ }
+ catch(std::out_of_range& fail) {
+ VERIFY( true );
+ }
+ catch(...) {
+ VERIFY( false );
+ }
}
int main()
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/3.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/3.cc
index 1bd3deb30f47..75f2dcf01300 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/3.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/char/3.cc
@@ -19,11 +19,13 @@
// 21.3.5 string modifiers
+#include <stdexcept>
#include <string>
#include <testsuite_hooks.h>
// assign(const _CharT* __s, size_type __n)
// assign(const _CharT* __s)
+// assign(const _CharT* __s, size_type __pos, size_type __n)
void
test03()
{
@@ -47,6 +49,20 @@ test03()
one.assign(one.c_str() + 8, 6);
VERIFY( one == "by the" );
+
+ one.assign(one.c_str(), 3, 3);
+ VERIFY( one == "the" );
+
+ try {
+ one.assign("a\0b", 2, 1);
+ VERIFY( false );
+ }
+ catch(std::out_of_range& fail) {
+ VERIFY( true );
+ }
+ catch(...) {
+ VERIFY( false );
+ }
}
int main()
diff --git a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/3.cc b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/3.cc
index e7fcb231dff6..821cde246bd5 100644
--- a/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/3.cc
+++ b/libstdc++-v3/testsuite/21_strings/basic_string/modifiers/assign/wchar_t/3.cc
@@ -19,11 +19,13 @@
// 21.3.5 string modifiers
+#include <stdexcept>
#include <string>
#include <testsuite_hooks.h>
// assign(const _CharT* __s, size_type __n)
// assign(const _CharT* __s)
+// assign(const _CharT* __s, size_type __pos, size_type __n)
void
test03()
{
@@ -47,6 +49,20 @@ test03()
one.assign(one.c_str() + 8, 6);
VERIFY( one == L"by the" );
+
+ one.assign(one.c_str(), 3, 3);
+ VERIFY( one == L"the" );
+
+ try {
+ one.assign(L"a\0b", 2, 1);
+ VERIFY( false );
+ }
+ catch(std::out_of_range& fail) {
+ VERIFY( true );
+ }
+ catch(...) {
+ VERIFY( false );
+ }
}
int main()
More information about the Libstdc++-cvs
mailing list