Hi!

This patch implements LWG3662 for C++11 ABI and COW ABI of strings.

Tested on x86_64 linux, ok for trunk?

Thanks,
Yuao
From fc49215982b5bcf47fcca9171e2a9a82f2fdec18 Mon Sep 17 00:00:00 2001
From: Yuao Ma <[email protected]>
Date: Wed, 1 Jul 2026 22:36:33 +0800
Subject: [PATCH] libstdc++: implement LWG3662
 basic_string::append/assign(NTBS, pos, n) suboptimal

This patch implements LWG3662 for both ABIs of std::string.

libstdc++-v3/ChangeLog:

        * include/bits/basic_string.h: Add new append/assign API.
        * include/bits/cow_string.h: Ditto.
        * testsuite/21_strings/basic_string/modifiers/append/char/2.cc: Test 
new API.
        * 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.
---
 libstdc++-v3/include/bits/basic_string.h      | 31 +++++++++++++++++++
 libstdc++-v3/include/bits/cow_string.h        | 29 +++++++++++++++++
 .../basic_string/modifiers/append/char/2.cc   |  4 +++
 .../modifiers/append/wchar_t/2.cc             |  4 +++
 .../basic_string/modifiers/assign/char/3.cc   |  4 +++
 .../modifiers/assign/wchar_t/3.cc             |  4 +++
 6 files changed, 76 insertions(+)

diff --git a/libstdc++-v3/include/bits/basic_string.h 
b/libstdc++-v3/include/bits/basic_string.h
index 65d92ebfbcf..69d45ceb01e 100644
--- a/libstdc++-v3/include/bits/basic_string.h
+++ b/libstdc++-v3/include/bits/basic_string.h
@@ -1639,6 +1639,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        return _M_append(__s, __n);
       }
 
+      /**
+       *  @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)
+      {
+       __glibcxx_requires_string_len(__s, __n);
+       _M_check_length(size_type(0), __n, "basic_string::append");
+       return append(__sv_type(__s).substr(__pos, __n));
+      }
+
       /**
        *  @brief  Append multiple characters.
        *  @param __n  The number of characters to append.
@@ -1902,6 +1918,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
                          traits_type::length(__s));
       }
 
+      /**
+       *  @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)
+      {
+       __glibcxx_requires_string_len(__s, __n);
+       return assign(__sv_type(__s).substr(__pos, __n));
+      }
+
       /**
        *  @brief  Set value to multiple characters.
        *  @param __n  Length of the resulting string.
diff --git a/libstdc++-v3/include/bits/cow_string.h 
b/libstdc++-v3/include/bits/cow_string.h
index 7c945f6b998..e89feda7a3c 100644
--- a/libstdc++-v3/include/bits/cow_string.h
+++ b/libstdc++-v3/include/bits/cow_string.h
@@ -1345,6 +1345,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return this->append(__s, traits_type::length(__s));
       }
 
+      /**
+       *  @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)
+      {
+       __glibcxx_requires_string_len(__s, __n);
+       _M_check_length(size_type(0), __n, "basic_string::append");
+       return append(__sv_type(__s).substr(__pos, __n));
+      }
+
       /**
        *  @brief  Append multiple characters.
        *  @param __n  The number of characters to append.
@@ -1517,6 +1532,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return this->assign(__s, traits_type::length(__s));
       }
 
+      /**
+       *  @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)
+      {
+       __glibcxx_requires_string_len(__s, __n);
+       return assign(__sv_type(__s).substr(__pos, __n));
+      }
+
       /**
        *  @brief  Set value to multiple characters.
        *  @param __n  Length of the resulting string.
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 d70fc190b45..5dd39347574 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
@@ -24,6 +24,7 @@
 
 // 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 +56,9 @@ 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" );
 }
 
 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 1922874de7f..fcc1ef54f28 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
@@ -24,6 +24,7 @@
 
 // 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 +56,9 @@ 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" );
 }
 
 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 1bd3deb30f4..a742c1ed3df 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
@@ -24,6 +24,7 @@
 
 // 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 +48,9 @@ test03()
 
   one.assign(one.c_str() + 8, 6);
   VERIFY( one == "by the" );
+
+  one.assign(one.c_str(), 3, 3);
+  VERIFY( one == "the" );
 }
 
 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 e7fcb231dff..37ff7e1ca2b 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
@@ -24,6 +24,7 @@
 
 // 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 +48,9 @@ test03()
 
   one.assign(one.c_str() + 8, 6);
   VERIFY( one == L"by the" );
+
+  one.assign(one.c_str(), 3, 3);
+  VERIFY( one == L"the" );
 }
 
 int main()
-- 
2.54.0

Reply via email to