[libcxx-commits] [libcxx] [libc++][strings] P2591R5: Concatenation of strings and string views (PR #88389)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Apr 15 23:41:58 PDT 2024
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/88389
>From 2d606f402e34d446322c44598ada051c14fa6057 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 11 Apr 2024 10:28:35 +0300
Subject: [PATCH 1/9] [libc++][strings] P2591R5: Concatenation of strings and
string views
Implemented: https://wg21.link/P2591R5
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +
libcxx/docs/ReleaseNotes/19.rst | 1 +
libcxx/docs/Status/Cxx2cPapers.csv | 2 +-
libcxx/include/string | 104 ++++++++++++++----
libcxx/include/version | 5 +-
.../string.version.compile.pass.cpp | 5 +-
.../string_view.version.compile.pass.cpp | 5 +-
.../version.version.compile.pass.cpp | 5 +-
.../string_op+/string.string_view.pass.cpp | 76 +++++++++++++
.../generate_feature_test_macro_components.py | 2 +-
10 files changed, 176 insertions(+), 31 deletions(-)
create mode 100644 libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 3197d2cd1b271c..0b8abe38e8bd77 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -456,6 +456,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_sstream_from_string_view`` ``202306L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_string_view`` ``202403L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_submdspan`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_text_encoding`` *unimplemented*
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index 81c05b9112bd26..6fbac70593cc0b 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -45,6 +45,7 @@ Implemented Papers
- P2867R2 - Remove Deprecated ``strstream``\s From C++26
- P2872R3 - Remove ``wstring_convert`` From C++26
- P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23)
+- P2591R5 - Concatenation of strings and string views
- P2302R4 - ``std::ranges::contains``
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index fa11da62bc080e..8793d9385b79ae 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -55,7 +55,7 @@
"`P2845R8 <https://wg21.link/P2845R8>`__","LWG","Formatting of ``std::filesystem::path``","Tokyo March 2024","","","|format|"
"`P0493R5 <https://wg21.link/P0493R5>`__","LWG","Atomic minimum/maximum","Tokyo March 2024","","",""
"`P2542R8 <https://wg21.link/P2542R8>`__","LWG","``views::concat``","Tokyo March 2024","","","|ranges|"
-"`P2591R5 <https://wg21.link/P2591R5>`__","LWG","Concatenation of strings and string views","Tokyo March 2024","","",""
+"`P2591R5 <https://wg21.link/P2591R5>`__","LWG","Concatenation of strings and string views","Tokyo March 2024","|Complete|","19.0",""
"`P2248R8 <https://wg21.link/P2248R8>`__","LWG","Enabling list-initialization for algorithms","Tokyo March 2024","","",""
"`P2810R4 <https://wg21.link/P2810R4>`__","LWG","``is_debugger_present`` ``is_replaceable``","Tokyo March 2024","","",""
"`P1068R11 <https://wg21.link/P1068R11>`__","LWG","Vector API for random number generation","Tokyo March 2024","","",""
diff --git a/libcxx/include/string b/libcxx/include/string
index a456f8cb80ee35..7758a4ae42e046 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -407,6 +407,24 @@ template<class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator>
operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs); // constexpr since C++20
+template<class charT, class traits, class Allocator>
+ constexpr basic_string<charT, traits, Allocator>
+ operator+(const basic_string<charT, traits, Allocator>& lhs,
+ type_identity_t<basic_string_view<charT, traits>> rhs); // Since C++26
+template<class charT, class traits, class Allocator>
+ constexpr basic_string<charT, traits, Allocator>
+ operator+(basic_string<charT, traits, Allocator>&& lhs,
+ type_identity_t<basic_string_view<charT, traits>> rhs); // Since C++26
+template<class charT, class traits, class Allocator>
+ constexpr basic_string<charT, traits, Allocator>
+ operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
+ const basic_string<charT, traits, Allocator>& rhs); // Since C++26
+template<class charT, class traits, class Allocator>
+ constexpr basic_string<charT, traits, Allocator>
+ operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
+ basic_string<charT, traits, Allocator>&& rhs); // Since C++26
+
+
template<class charT, class traits, class Allocator>
bool operator==(const basic_string<charT, traits, Allocator>& lhs,
const basic_string<charT, traits, Allocator>& rhs) noexcept; // constexpr since C++20
@@ -1074,8 +1092,8 @@ public:
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
!__is_same_uncvref<_Tp, basic_string>::value,
int> = 0>
- _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(
- const _Tp& __t, const allocator_type& __a)
+ _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
+ _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a)
: __r_(__default_init_tag(), __a) {
__self_view __sv = __t;
__init(__sv.data(), __sv.size());
@@ -1307,8 +1325,8 @@ public:
int> = 0>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
- basic_string&
- append(const _Tp& __t, size_type __pos, size_type __n = npos);
+ basic_string&
+ append(const _Tp& __t, size_type __pos, size_type __n = npos);
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s);
@@ -1997,15 +2015,15 @@ private:
_LIBCPP_CONSTEXPR_SINCE_CXX20
#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1
- _LIBCPP_HIDE_FROM_ABI
+ _LIBCPP_HIDE_FROM_ABI
#endif
- _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by(
- size_type __old_cap,
- size_type __delta_cap,
- size_type __old_sz,
- size_type __n_copy,
- size_type __n_del,
- size_type __n_add = 0);
+ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by(
+ size_type __old_cap,
+ size_type __delta_cap,
+ size_type __old_sz,
+ size_type __n_copy,
+ size_type __n_del,
+ size_type __n_add = 0);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __grow_by_without_replace(
size_type __old_cap,
size_type __delta_cap,
@@ -2171,8 +2189,8 @@ template <class _CharT,
class _Traits,
class _Allocator = allocator<_CharT>,
class = enable_if_t<__is_allocator<_Allocator>::value> >
-explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
- -> basic_string<_CharT, _Traits, _Allocator>;
+explicit basic_string(basic_string_view<_CharT, _Traits>,
+ const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>;
template <class _CharT,
class _Traits,
@@ -2407,15 +2425,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
template <class _CharT, class _Traits, class _Allocator>
void _LIBCPP_CONSTEXPR_SINCE_CXX20
#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1
- _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_HIDE_FROM_ABI
#endif
- _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by(
- size_type __old_cap,
- size_type __delta_cap,
- size_type __old_sz,
- size_type __n_copy,
- size_type __n_del,
- size_type __n_add) {
+_LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by(
+ size_type __old_cap,
+ size_type __delta_cap,
+ size_type __old_sz,
+ size_type __n_copy,
+ size_type __n_del,
+ size_type __n_add) {
size_type __ms = max_size();
if (__delta_cap > __ms - __old_cap)
__throw_length_error();
@@ -4005,6 +4023,48 @@ operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) {
#endif // _LIBCPP_CXX03_LANG
+#if _LIBCPP_STD_VER >= 26
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
+ type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) {
+ using _String = basic_string<_CharT, _Traits, _Allocator>;
+
+ _String __r = __lhs;
+ __r.append(__rhs);
+ return __r;
+}
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs,
+ type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) {
+ __lhs.append(__rhs);
+ return std::move(__lhs);
+}
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
+ const basic_string<_CharT, _Traits, _Allocator>& __rhs) {
+ using _String = basic_string<_CharT, _Traits, _Allocator>;
+
+ _String __r = __rhs;
+ __r.insert(0, __lhs);
+ return __r;
+}
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
+ basic_string<_CharT, _Traits, _Allocator>&& __rhs) {
+ __rhs.insert(0, __lhs);
+ return std::move(__rhs);
+}
+
+#endif // _LIBCPP_STD_VER >= 26
+
// swap
template <class _CharT, class _Traits, class _Allocator>
diff --git a/libcxx/include/version b/libcxx/include/version
index 0ed77345baa71d..d7e98fdb47208d 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -222,7 +222,8 @@ __cpp_lib_stdatomic_h 202011L <stdatomic.h>
__cpp_lib_string_contains 202011L <string> <string_view>
__cpp_lib_string_resize_and_overwrite 202110L <string>
__cpp_lib_string_udls 201304L <string>
-__cpp_lib_string_view 201803L <string> <string_view>
+__cpp_lib_string_view 202403L <string> <string_view>
+ 201803L // C++20
201606L // C++17
__cpp_lib_submdspan 202306L <mdspan>
__cpp_lib_syncbuf 201803L <syncstream>
@@ -530,6 +531,8 @@ __cpp_lib_within_lifetime 202306L <type_traits>
# define __cpp_lib_span_at 202311L
# define __cpp_lib_span_initializer_list 202311L
# define __cpp_lib_sstream_from_string_view 202306L
+# undef __cpp_lib_string_view
+# define __cpp_lib_string_view 202403L
// # define __cpp_lib_submdspan 202306L
// # define __cpp_lib_text_encoding 202306L
# undef __cpp_lib_to_chars
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
index 8d944a194faf42..4fb733716b99e2 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp
@@ -29,6 +29,7 @@
__cpp_lib_string_udls 201304L [C++14]
__cpp_lib_string_view 201606L [C++17]
201803L [C++20]
+ 202403L [C++26]
__cpp_lib_to_string 202306L [C++23]
*/
@@ -492,8 +493,8 @@
# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++26"
# endif
-# if __cpp_lib_string_view != 201803L
-# error "__cpp_lib_string_view should have the value 201803L in c++26"
+# if __cpp_lib_string_view != 202403L
+# error "__cpp_lib_string_view should have the value 202403L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
index a86ab2adff6a93..f3c70cf9779737 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp
@@ -23,6 +23,7 @@
__cpp_lib_string_contains 202011L [C++23]
__cpp_lib_string_view 201606L [C++17]
201803L [C++20]
+ 202403L [C++26]
*/
#include <string_view>
@@ -252,8 +253,8 @@
# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++26"
# endif
-# if __cpp_lib_string_view != 201803L
-# error "__cpp_lib_string_view should have the value 201803L in c++26"
+# if __cpp_lib_string_view != 202403L
+# error "__cpp_lib_string_view should have the value 202403L in c++26"
# endif
#endif // TEST_STD_VER > 23
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 3ec548f56cea1d..35bbfd916ac80a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -206,6 +206,7 @@
__cpp_lib_string_udls 201304L [C++14]
__cpp_lib_string_view 201606L [C++17]
201803L [C++20]
+ 202403L [C++26]
__cpp_lib_submdspan 202306L [C++26]
__cpp_lib_syncbuf 201803L [C++20]
__cpp_lib_text_encoding 202306L [C++26]
@@ -7686,8 +7687,8 @@
# ifndef __cpp_lib_string_view
# error "__cpp_lib_string_view should be defined in c++26"
# endif
-# if __cpp_lib_string_view != 201803L
-# error "__cpp_lib_string_view should have the value 201803L in c++26"
+# if __cpp_lib_string_view != 202403L
+# error "__cpp_lib_string_view should have the value 202403L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
new file mode 100644
index 00000000000000..efa57442997e7f
--- /dev/null
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -0,0 +1,76 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
+
+// <string>
+
+// [string.op.plus]
+//
+// template<class charT, class traits, class Allocator>
+// constexpr basic_string<charT, traits, Allocator>
+// operator+(const basic_string<charT, traits, Allocator>& lhs,
+// type_identity_t<basic_string_view<charT, traits>> rhs); // Since C++26
+// template<class charT, class traits, class Allocator>
+// constexpr basic_string<charT, traits, Allocator>
+// operator+(basic_string<charT, traits, Allocator>&& lhs,
+// type_identity_t<basic_string_view<charT, traits>> rhs); // Since C++26
+// template<class charT, class traits, class Allocator>
+// constexpr basic_string<charT, traits, Allocator>
+// operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
+// const basic_string<charT, traits, Allocator>& rhs); // Since C++26
+// template<class charT, class traits, class Allocator>
+// constexpr basic_string<charT, traits, Allocator>
+// operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
+// basic_string<charT, traits, Allocator>&& rhs); // Since C++26
+
+#include <cassert>
+#include <string>
+#include <utility>
+
+#include "asan_testing.h"
+#include "constexpr_char_traits.h"
+#include "make_string.h"
+#include "min_allocator.h"
+#include "test_macros.h"
+
+#define CS(S) MAKE_CSTRING(CharT, S)
+#define ST(S, a) std::basic_string<CharT, TraitsT, AllocT>(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a)
+#define SV(S) std::basic_string_view<CharT, TraitsT>(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S))
+
+template <typename CharT, typename TraitsT, typename AllocT>
+constexpr void test() {
+ AllocT allocator;
+ std::basic_string<CharT, TraitsT, AllocT> st{ST("Hello", allocator)};
+ std::basic_string_view<CharT, TraitsT> sv{SV("World")};
+
+ assert(st + sv == ST("HelloWorld", allocator));
+ assert(st + sv != ST("Hello World", allocator));
+}
+
+constexpr bool test() {
+ test<char, std::char_traits<char>, min_allocator<char>>();
+ test<char, constexpr_char_traits<char>, min_allocator<char>>();
+ test<char, std::char_traits<char>, safe_allocator<char>>();
+ test<char, constexpr_char_traits<char>, safe_allocator<char>>();
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
+ test<wchar_t, constexpr_char_traits<wchar_t>, min_allocator<wchar_t>>();
+ test<wchar_t, std::char_traits<wchar_t>, safe_allocator<wchar_t>>();
+ test<wchar_t, constexpr_char_traits<wchar_t>, safe_allocator<wchar_t>>();
+#endif
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index f2b8d55c0e11b0..1afdb6475b1877 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1202,7 +1202,7 @@ def add_version_header(tc):
"values": {
"c++17": 201606,
"c++20": 201803,
- # "c++26": 202403, # P2591R5: Concatenation of strings and string views
+ "c++26": 202403, # P2591R5: Concatenation of strings and string views
},
"headers": ["string", "string_view"],
},
>From af56ab902866a6971fad6034b483ad55e02ccdef Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 11 Apr 2024 21:01:34 +0300
Subject: [PATCH 2/9] Implemented tests
---
libcxx/include/string | 11 +-
.../string_op+/string.string_view.pass.cpp | 107 ++++++++++++++++--
.../generate_feature_test_macro_components.py | 2 +-
3 files changed, 107 insertions(+), 13 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 7758a4ae42e046..eb5f2b78af082b 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -4050,8 +4050,8 @@ operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs) {
using _String = basic_string<_CharT, _Traits, _Allocator>;
- _String __r = __rhs;
- __r.insert(0, __lhs);
+ _String __r{__lhs};
+ __r.append(__rhs);
return __r;
}
@@ -4059,8 +4059,11 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
basic_string<_CharT, _Traits, _Allocator>&& __rhs) {
- __rhs.insert(0, __lhs);
- return std::move(__rhs);
+ using _String = basic_string<_CharT, _Traits, _Allocator>;
+
+ _String __r{__lhs};
+ __r.append(std::move(__rhs));
+ return __r;
}
#endif // _LIBCPP_STD_VER >= 26
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
index efa57442997e7f..21936d76d06320 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -30,6 +30,7 @@
// basic_string<charT, traits, Allocator>&& rhs); // Since C++26
#include <cassert>
+#include <concepts>
#include <string>
#include <utility>
@@ -37,6 +38,7 @@
#include "constexpr_char_traits.h"
#include "make_string.h"
#include "min_allocator.h"
+#include "test_allocator.h"
#include "test_macros.h"
#define CS(S) MAKE_CSTRING(CharT, S)
@@ -44,25 +46,114 @@
#define SV(S) std::basic_string_view<CharT, TraitsT>(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S))
template <typename CharT, typename TraitsT, typename AllocT>
-constexpr void test() {
+constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
AllocT allocator;
- std::basic_string<CharT, TraitsT, AllocT> st{ST("Hello", allocator)};
- std::basic_string_view<CharT, TraitsT> sv{SV("World")};
- assert(st + sv == ST("HelloWorld", allocator));
- assert(st + sv != ST("Hello World", allocator));
+ // string& + string_view
+ {
+ std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ std::basic_string_view<CharT, TraitsT> sv{y};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + sv;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(st + sv));
+ }
+ // const string& + string_view
+ {
+ const std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ std::basic_string_view<CharT, TraitsT> sv{y};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + sv;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(st + sv));
+ }
+ // string&& + string_view
+ {
+ std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ std::basic_string_view<CharT, TraitsT> sv{y};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = std::move(st) + sv;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(st + sv));
+ }
+ // string_view + string&
+ {
+ std::basic_string_view<CharT, TraitsT> sv{x};
+ std::basic_string<CharT, TraitsT, AllocT> st{y, allocator};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = sv + st;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(sv + st));
+ }
+ // string_view + const string&
+ {
+ std::basic_string_view<CharT, TraitsT> sv{x};
+ const std::basic_string<CharT, TraitsT, AllocT> st{y, allocator};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = sv + st;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(sv + st));
+ }
+ // string_view + string&&
+ {
+ std::basic_string_view<CharT, TraitsT> sv{x};
+ std::basic_string<CharT, TraitsT, AllocT> st{y, allocator};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = sv + std::move(st);
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(sv + st));
+ }
+}
+
+template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+constexpr void test() {
+ // Concatinate with an empty string
+ test<CharT, TraitsT, AllocT>(CS(""), CS(""), CS(""));
+ test<CharT, TraitsT, AllocT>(CS(""), CS("short"), CS("short"));
+ test<CharT, TraitsT, AllocT>(CS(""), CS("not so short"), CS("not so short"));
+ test<CharT, TraitsT, AllocT>(CS(""), CS("this is a much longer string"), CS("this is a much longer string"));
+
+ test<CharT, TraitsT, AllocT>(CS(""), CS(""), CS(""));
+ test<CharT, TraitsT, AllocT>(CS("short"), CS(""), CS("short"));
+ test<CharT, TraitsT, AllocT>(CS("not so short"), CS(""), CS("not so short"));
+ test<CharT, TraitsT, AllocT>(CS("this is a much longer string"), CS(""), CS("this is a much longer string"));
+
+ // Non empty
+ test<CharT, TraitsT, AllocT>(CS("B"), CS("D"), CS("BD"));
+ test<CharT, TraitsT, AllocT>(CS("zmt94"), CS("+hkt82"), CS("zmt94+hkt82"));
+ test<CharT, TraitsT, AllocT>(CS("not so short"), CS("+is not bad"), CS("not so short+is not bad"));
+ test<CharT, TraitsT, AllocT>(
+ CS("this is a much longer string"),
+ CS("+which is so much better"),
+ CS("this is a much longer string+which is so much better"));
}
constexpr bool test() {
+ test<char, std::char_traits<char>>();
test<char, std::char_traits<char>, min_allocator<char>>();
- test<char, constexpr_char_traits<char>, min_allocator<char>>();
test<char, std::char_traits<char>, safe_allocator<char>>();
+ // test<char, std::char_traits<char>, test_allocator<char>>();
+
+ test<char, constexpr_char_traits<char>>();
+ test<char, constexpr_char_traits<char>, min_allocator<char>>();
test<char, constexpr_char_traits<char>, safe_allocator<char>>();
+ // test<char, constexpr_char_traits<char>, test_allocator<char>>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
- test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
- test<wchar_t, constexpr_char_traits<wchar_t>, min_allocator<wchar_t>>();
+ test<wchar_t, std::char_traits<wchar_t>>();
+ // test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, std::char_traits<wchar_t>, safe_allocator<wchar_t>>();
+ // test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
+
+ test<wchar_t, constexpr_char_traits<wchar_t>>();
+ // test<wchar_t, constexpr_char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, constexpr_char_traits<wchar_t>, safe_allocator<wchar_t>>();
+ // test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
#endif
return true;
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 1afdb6475b1877..1b938fa30c59d2 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1202,7 +1202,7 @@ def add_version_header(tc):
"values": {
"c++17": 201606,
"c++20": 201803,
- "c++26": 202403, # P2591R5: Concatenation of strings and string views
+ "c++26": 202403, # P2591R5: Concatenation of strings and string views
},
"headers": ["string", "string_view"],
},
>From 474d5b9d8a15921369614cf82df46502fad13f7f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 11 Apr 2024 21:03:43 +0300
Subject: [PATCH 3/9] Cleanup
---
.../string_op+/string.string_view.pass.cpp | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
index 21936d76d06320..f2fb1dbe7195de 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -38,7 +38,6 @@
#include "constexpr_char_traits.h"
#include "make_string.h"
#include "min_allocator.h"
-#include "test_allocator.h"
#include "test_macros.h"
#define CS(S) MAKE_CSTRING(CharT, S)
@@ -113,7 +112,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
constexpr void test() {
- // Concatinate with an empty string
+ // Concatinate with an empty `string`/`string_view`
test<CharT, TraitsT, AllocT>(CS(""), CS(""), CS(""));
test<CharT, TraitsT, AllocT>(CS(""), CS("short"), CS("short"));
test<CharT, TraitsT, AllocT>(CS(""), CS("not so short"), CS("not so short"));
@@ -138,22 +137,16 @@ constexpr bool test() {
test<char, std::char_traits<char>>();
test<char, std::char_traits<char>, min_allocator<char>>();
test<char, std::char_traits<char>, safe_allocator<char>>();
- // test<char, std::char_traits<char>, test_allocator<char>>();
test<char, constexpr_char_traits<char>>();
test<char, constexpr_char_traits<char>, min_allocator<char>>();
test<char, constexpr_char_traits<char>, safe_allocator<char>>();
- // test<char, constexpr_char_traits<char>, test_allocator<char>>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t, std::char_traits<wchar_t>>();
- // test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, std::char_traits<wchar_t>, safe_allocator<wchar_t>>();
- // test<wchar_t, std::char_traits<wchar_t>, test_allocator<wchar_t>>();
test<wchar_t, constexpr_char_traits<wchar_t>>();
- // test<wchar_t, constexpr_char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, constexpr_char_traits<wchar_t>, safe_allocator<wchar_t>>();
- // test<wchar_t, constexpr_char_traits<wchar_t>, test_allocator<wchar_t>>();
#endif
return true;
>From 38f6e853deb3dbc6b9020de509f30cfeb981b12f Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 11 Apr 2024 21:06:16 +0300
Subject: [PATCH 4/9] Restored formatting
---
libcxx/include/string | 44 +++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index eb5f2b78af082b..5af81486fa30d7 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1092,8 +1092,8 @@ public:
__enable_if_t<__can_be_converted_to_string_view<_CharT, _Traits, _Tp>::value &&
!__is_same_uncvref<_Tp, basic_string>::value,
int> = 0>
- _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS
- _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(const _Tp& __t, const allocator_type& __a)
+ _LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20 explicit basic_string(
+ const _Tp& __t, const allocator_type& __a)
: __r_(__default_init_tag(), __a) {
__self_view __sv = __t;
__init(__sv.data(), __sv.size());
@@ -1325,8 +1325,8 @@ public:
int> = 0>
_LIBCPP_METHOD_TEMPLATE_IMPLICIT_INSTANTIATION_VIS _LIBCPP_CONSTEXPR_SINCE_CXX20
- basic_string&
- append(const _Tp& __t, size_type __pos, size_type __n = npos);
+ basic_string&
+ append(const _Tp& __t, size_type __pos, size_type __n = npos);
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s, size_type __n);
_LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string& append(const value_type* __s);
@@ -2015,15 +2015,15 @@ private:
_LIBCPP_CONSTEXPR_SINCE_CXX20
#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1
- _LIBCPP_HIDE_FROM_ABI
+ _LIBCPP_HIDE_FROM_ABI
#endif
- _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by(
- size_type __old_cap,
- size_type __delta_cap,
- size_type __old_sz,
- size_type __n_copy,
- size_type __n_del,
- size_type __n_add = 0);
+ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") void __grow_by(
+ size_type __old_cap,
+ size_type __delta_cap,
+ size_type __old_sz,
+ size_type __n_copy,
+ size_type __n_del,
+ size_type __n_add = 0);
_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __grow_by_without_replace(
size_type __old_cap,
size_type __delta_cap,
@@ -2189,8 +2189,8 @@ template <class _CharT,
class _Traits,
class _Allocator = allocator<_CharT>,
class = enable_if_t<__is_allocator<_Allocator>::value> >
-explicit basic_string(basic_string_view<_CharT, _Traits>,
- const _Allocator& = _Allocator()) -> basic_string<_CharT, _Traits, _Allocator>;
+explicit basic_string(basic_string_view<_CharT, _Traits>, const _Allocator& = _Allocator())
+ -> basic_string<_CharT, _Traits, _Allocator>;
template <class _CharT,
class _Traits,
@@ -2425,15 +2425,15 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
template <class _CharT, class _Traits, class _Allocator>
void _LIBCPP_CONSTEXPR_SINCE_CXX20
#if _LIBCPP_ABI_VERSION >= 2 // We want to use the function in the dylib in ABIv1
-_LIBCPP_HIDE_FROM_ABI
+ _LIBCPP_HIDE_FROM_ABI
#endif
-_LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by(
- size_type __old_cap,
- size_type __delta_cap,
- size_type __old_sz,
- size_type __n_copy,
- size_type __n_del,
- size_type __n_add) {
+ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Traits, _Allocator>::__grow_by(
+ size_type __old_cap,
+ size_type __delta_cap,
+ size_type __old_sz,
+ size_type __n_copy,
+ size_type __n_del,
+ size_type __n_add) {
size_type __ms = max_size();
if (__delta_cap > __ms - __old_cap)
__throw_length_error();
>From ea270b6f3aff22da6cf8513fe2867453740b491c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 13 Apr 2024 07:12:20 +0300
Subject: [PATCH 5/9] Addressed review comments
---
libcxx/include/string | 17 +++++------------
.../string_op+/string.string_view.pass.cpp | 2 ++
2 files changed, 7 insertions(+), 12 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 5af81486fa30d7..bd648a33b5cdd9 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -4029,9 +4029,7 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) {
- using _String = basic_string<_CharT, _Traits, _Allocator>;
-
- _String __r = __lhs;
+ basic_string<_CharT, _Traits, _Allocator> __r = __lhs;
__r.append(__rhs);
return __r;
}
@@ -4048,10 +4046,8 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs) {
- using _String = basic_string<_CharT, _Traits, _Allocator>;
-
- _String __r{__lhs};
- __r.append(__rhs);
+ basic_string<_CharT, _Traits, _Allocator> __r = __rhs;
+ __r.insert(0, __lhs);
return __r;
}
@@ -4059,11 +4055,8 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
basic_string<_CharT, _Traits, _Allocator>&& __rhs) {
- using _String = basic_string<_CharT, _Traits, _Allocator>;
-
- _String __r{__lhs};
- __r.append(std::move(__rhs));
- return __r;
+ __rhs.insert(0, __lhs);
+ return std::move(__rhs);
}
#endif // _LIBCPP_STD_VER >= 26
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
index f2fb1dbe7195de..2d0981ed450be1 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -143,9 +143,11 @@ constexpr bool test() {
test<char, constexpr_char_traits<char>, safe_allocator<char>>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t, std::char_traits<wchar_t>>();
+ test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, std::char_traits<wchar_t>, safe_allocator<wchar_t>>();
test<wchar_t, constexpr_char_traits<wchar_t>>();
+ test<wchar_t, constexpr_char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, constexpr_char_traits<wchar_t>, safe_allocator<wchar_t>>();
#endif
>From 292cd8f7a485d8ccdf9635c50bba1c4a88fc7532 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sat, 13 Apr 2024 07:13:20 +0300
Subject: [PATCH 6/9] Removed `constexpr_char_traits` tests
---
.../string_op+/string.string_view.pass.cpp | 7 -------
1 file changed, 7 deletions(-)
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
index 2d0981ed450be1..7f08d460a6fb12 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -138,17 +138,10 @@ constexpr bool test() {
test<char, std::char_traits<char>, min_allocator<char>>();
test<char, std::char_traits<char>, safe_allocator<char>>();
- test<char, constexpr_char_traits<char>>();
- test<char, constexpr_char_traits<char>, min_allocator<char>>();
- test<char, constexpr_char_traits<char>, safe_allocator<char>>();
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t, std::char_traits<wchar_t>>();
test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
test<wchar_t, std::char_traits<wchar_t>, safe_allocator<wchar_t>>();
-
- test<wchar_t, constexpr_char_traits<wchar_t>>();
- test<wchar_t, constexpr_char_traits<wchar_t>, min_allocator<wchar_t>>();
- test<wchar_t, constexpr_char_traits<wchar_t>, safe_allocator<wchar_t>>();
#endif
return true;
>From 9a86ea1a9c1c0eefca8bec6223b14bec108ee445 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 15 Apr 2024 12:23:24 +0300
Subject: [PATCH 7/9] Use Will Hawkins implementation
---
libcxx/include/string | 88 +++++++++++++++++--
.../string_op+/string.string_view.pass.cpp | 52 ++++++++---
2 files changed, 121 insertions(+), 19 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index bd648a33b5cdd9..2a8cbb0b49072e 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -725,6 +725,26 @@ struct __can_be_converted_to_string_view
struct __uninitialized_size_tag {};
struct __init_with_sentinel_tag {};
+#if _LIBCPP_STD_VER >= 26
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
+ type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
+ const basic_string<_CharT, _Traits, _Allocator>& __rhs);
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs);
+#endif
+
template <class _CharT, class _Traits, class _Allocator>
class basic_string {
private:
@@ -2158,6 +2178,30 @@ private:
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(value_type, const basic_string&);
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const value_type*);
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, value_type);
+#if _LIBCPP_STD_VER >= 26
+ // friend constexpr basic_string operator+ <>(const basic_string&, const __self_view&);
+
+ // friend constexpr basic_string operator+ <>(const __self_view&, const basic_string&);
+
+ // friend constexpr operator+ <>(type_identity_t<__self_view> __lhs,
+ // const basic_string& __rhs);
+
+ // friend constexpr basic_string operator+
+ // <>(type_identity_t<basic_string_view<_CharT2, _Traits2>> __lhs,
+ // const basic_string<_CharT2, _Traits2, _Allocator2>& __rhs);
+
+ // template <class _CharT2, class _Traits2, class _Allocator2>
+ // friend constexpr basic_string<_CharT2, _Traits2, _Allocator2>
+ // operator+(type_identity_t<basic_string_view<_CharT2, _Traits2>>, const basic_string<_CharT2, _Traits2, _Allocator2>&);
+
+
+ // friend constexpr basic_string operator+ <>(type_identity_t<basic_string_view>, const basic_string&);
+
+ friend constexpr basic_string operator+ <>(const basic_string&, type_identity_t<__self_view>);
+ friend constexpr basic_string operator+ <>(basic_string&&, type_identity_t<__self_view>);
+ friend constexpr basic_string operator+ <>(type_identity_t<__self_view>, const basic_string&);
+ friend constexpr basic_string operator+ <>(type_identity_t<__self_view>, basic_string&&);
+#endif
};
// These declarations must appear before any functions are implicitly used
@@ -4029,9 +4073,17 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) {
- basic_string<_CharT, _Traits, _Allocator> __r = __lhs;
- __r.append(__rhs);
- return __r;
+ using _String = basic_string<_CharT, _Traits, _Allocator>;
+ typename _String::size_type __lhs_sz = __lhs.size();
+ typename _String::size_type __rhs_sz = __rhs.size();
+ _String __r(__uninitialized_size_tag(),
+ __lhs_sz + __rhs_sz,
+ _String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
+ auto __ptr = std::__to_address(__r.__get_pointer());
+ _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
+ _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
+ _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
+ return __r;
}
template <class _CharT, class _Traits, class _Allocator>
@@ -4046,8 +4098,19 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs) {
- basic_string<_CharT, _Traits, _Allocator> __r = __rhs;
- __r.insert(0, __lhs);
+ // basic_string<_CharT, _Traits, _Allocator> __r = __rhs;
+ // __r.insert(0, __lhs);
+ // return __r;
+ using _String = basic_string<_CharT, _Traits, _Allocator>;
+ typename _String::size_type __lhs_sz = __lhs.size();
+ typename _String::size_type __rhs_sz = __rhs.size();
+ _String __r(__uninitialized_size_tag(),
+ __lhs_sz + __rhs_sz,
+ _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
+ auto __ptr = std::__to_address(__r.__get_pointer());
+ _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
+ _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
+ _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
return __r;
}
@@ -4055,8 +4118,19 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
basic_string<_CharT, _Traits, _Allocator>&& __rhs) {
- __rhs.insert(0, __lhs);
- return std::move(__rhs);
+ // __rhs.insert(0, __lhs);
+ // return std::move(__rhs);
+ using _String = basic_string<_CharT, _Traits, _Allocator>;
+ typename _String::size_type __lhs_sz = __lhs.size();
+ typename _String::size_type __rhs_sz = __rhs.size();
+ _String __r(__uninitialized_size_tag(),
+ __lhs_sz + __rhs_sz,
+ _String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
+ auto __ptr = std::__to_address(__r.__get_pointer());
+ _Traits::copy(__ptr, __lhs.data(), __lhs_sz);
+ _Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
+ _Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
+ return __r;
}
#endif // _LIBCPP_STD_VER >= 26
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
index 7f08d460a6fb12..28a14950eef0aa 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -110,9 +110,9 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
}
-template <typename CharT, typename TraitsT = std::char_traits<CharT>, typename AllocT = std::allocator<CharT>>
+template <typename CharT, typename TraitsT, typename AllocT = std::allocator<CharT>>
constexpr void test() {
- // Concatinate with an empty `string`/`string_view`
+ // Concatenate with an empty `string`/`string_view`
test<CharT, TraitsT, AllocT>(CS(""), CS(""), CS(""));
test<CharT, TraitsT, AllocT>(CS(""), CS("short"), CS("short"));
test<CharT, TraitsT, AllocT>(CS(""), CS("not so short"), CS("not so short"));
@@ -133,23 +133,51 @@ constexpr void test() {
CS("this is a much longer string+which is so much better"));
}
+template <typename CharT>
constexpr bool test() {
- test<char, std::char_traits<char>>();
- test<char, std::char_traits<char>, min_allocator<char>>();
- test<char, std::char_traits<char>, safe_allocator<char>>();
+ test<CharT, std::char_traits<CharT>>();
+ test<CharT, std::char_traits<CharT>, min_allocator<CharT>>();
+ test<CharT, std::char_traits<CharT>, safe_allocator<CharT>>();
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
- test<wchar_t, std::char_traits<wchar_t>>();
- test<wchar_t, std::char_traits<wchar_t>, min_allocator<wchar_t>>();
- test<wchar_t, std::char_traits<wchar_t>, safe_allocator<wchar_t>>();
-#endif
+ test<CharT, constexpr_char_traits<CharT>>();
+ test<CharT, constexpr_char_traits<CharT>, min_allocator<CharT>>();
+ test<CharT, constexpr_char_traits<CharT>, safe_allocator<CharT>>();
return true;
}
+// constexpr bool test() {
+// test<char>();
+// #ifndef TEST_HAS_NO_WIDE_CHARACTERS
+// test<wchar_t>();
+// #endif
+// #ifndef TEST_HAS_NO_CHAR8_T
+// test<char8_t>();
+// #endif
+// test<char16_t>();
+// test<char32_t>();
+
+// return true;
+// }
+
int main(int, char**) {
- test();
- static_assert(test());
+ // test();
+ // static_assert(test());
+
+ test<char>();
+ static_assert(test<char>());
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test<wchar_t>();
+ static_assert(test<wchar_t>());
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
+ test<char8_t>();
+ static_assert(test<char8_t>());
+#endif
+ test<char16_t>();
+ static_assert(test<char16_t>());
+ test<char32_t>();
+ static_assert(test<char32_t>());
return 0;
}
>From 695b4b61acaf072c75d573aeef3545276b04b99d Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 15 Apr 2024 12:28:33 +0300
Subject: [PATCH 8/9] Cleanup
---
libcxx/include/string | 28 -------------------
.../string_op+/string.string_view.pass.cpp | 20 ++-----------
2 files changed, 3 insertions(+), 45 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 2a8cbb0b49072e..a2606b73d5e578 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -731,10 +731,6 @@ _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
-template <class _CharT, class _Traits, class _Allocator>
-_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
-operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
-
template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
@@ -2179,26 +2175,7 @@ private:
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const value_type*);
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, value_type);
#if _LIBCPP_STD_VER >= 26
- // friend constexpr basic_string operator+ <>(const basic_string&, const __self_view&);
-
- // friend constexpr basic_string operator+ <>(const __self_view&, const basic_string&);
-
- // friend constexpr operator+ <>(type_identity_t<__self_view> __lhs,
- // const basic_string& __rhs);
-
- // friend constexpr basic_string operator+
- // <>(type_identity_t<basic_string_view<_CharT2, _Traits2>> __lhs,
- // const basic_string<_CharT2, _Traits2, _Allocator2>& __rhs);
-
- // template <class _CharT2, class _Traits2, class _Allocator2>
- // friend constexpr basic_string<_CharT2, _Traits2, _Allocator2>
- // operator+(type_identity_t<basic_string_view<_CharT2, _Traits2>>, const basic_string<_CharT2, _Traits2, _Allocator2>&);
-
-
- // friend constexpr basic_string operator+ <>(type_identity_t<basic_string_view>, const basic_string&);
-
friend constexpr basic_string operator+ <>(const basic_string&, type_identity_t<__self_view>);
- friend constexpr basic_string operator+ <>(basic_string&&, type_identity_t<__self_view>);
friend constexpr basic_string operator+ <>(type_identity_t<__self_view>, const basic_string&);
friend constexpr basic_string operator+ <>(type_identity_t<__self_view>, basic_string&&);
#endif
@@ -4098,9 +4075,6 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
const basic_string<_CharT, _Traits, _Allocator>& __rhs) {
- // basic_string<_CharT, _Traits, _Allocator> __r = __rhs;
- // __r.insert(0, __lhs);
- // return __r;
using _String = basic_string<_CharT, _Traits, _Allocator>;
typename _String::size_type __lhs_sz = __lhs.size();
typename _String::size_type __rhs_sz = __rhs.size();
@@ -4118,8 +4092,6 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
basic_string<_CharT, _Traits, _Allocator>&& __rhs) {
- // __rhs.insert(0, __lhs);
- // return std::move(__rhs);
using _String = basic_string<_CharT, _Traits, _Allocator>;
typename _String::size_type __lhs_sz = __lhs.size();
typename _String::size_type __rhs_sz = __rhs.size();
diff --git a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
index 28a14950eef0aa..7efaa1125efb01 100644
--- a/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
+++ b/libcxx/test/std/strings/basic.string/string.nonmembers/string_op+/string.string_view.pass.cpp
@@ -38,6 +38,7 @@
#include "constexpr_char_traits.h"
#include "make_string.h"
#include "min_allocator.h"
+#include "test_allocator.h"
#include "test_macros.h"
#define CS(S) MAKE_CSTRING(CharT, S)
@@ -138,32 +139,17 @@ constexpr bool test() {
test<CharT, std::char_traits<CharT>>();
test<CharT, std::char_traits<CharT>, min_allocator<CharT>>();
test<CharT, std::char_traits<CharT>, safe_allocator<CharT>>();
+ test<CharT, std::char_traits<CharT>, test_allocator<CharT>>();
test<CharT, constexpr_char_traits<CharT>>();
test<CharT, constexpr_char_traits<CharT>, min_allocator<CharT>>();
test<CharT, constexpr_char_traits<CharT>, safe_allocator<CharT>>();
+ test<CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>();
return true;
}
-// constexpr bool test() {
-// test<char>();
-// #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-// test<wchar_t>();
-// #endif
-// #ifndef TEST_HAS_NO_CHAR8_T
-// test<char8_t>();
-// #endif
-// test<char16_t>();
-// test<char32_t>();
-
-// return true;
-// }
-
int main(int, char**) {
- // test();
- // static_assert(test());
-
test<char>();
static_assert(test<char>());
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
>From 6b77e5a8428bffcd124f5dffb157ca9732c809b9 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 16 Apr 2024 09:41:32 +0300
Subject: [PATCH 9/9] Reordered forward declared functions
---
libcxx/include/string | 34 ++++++++++++++++++----------------
1 file changed, 18 insertions(+), 16 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index fd6d894d0f63ec..65968d78163a2d 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -706,6 +706,24 @@ template <class _CharT, class _Traits, class _Allocator>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>
operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y);
+#if _LIBCPP_STD_VER >= 26
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
+ type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
+ const basic_string<_CharT, _Traits, _Allocator>& __rhs);
+
+template <class _CharT, class _Traits, class _Allocator>
+_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
+operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs);
+
+#endif
+
extern template _LIBCPP_EXPORTED_FROM_ABI string operator+
<char, char_traits<char>, allocator<char> >(char const*, string const&);
@@ -726,22 +744,6 @@ struct __can_be_converted_to_string_view
struct __uninitialized_size_tag {};
struct __init_with_sentinel_tag {};
-#if _LIBCPP_STD_VER >= 26
-template <class _CharT, class _Traits, class _Allocator>
-_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
-operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
- type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
-
-template <class _CharT, class _Traits, class _Allocator>
-_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
-operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
- const basic_string<_CharT, _Traits, _Allocator>& __rhs);
-
-template <class _CharT, class _Traits, class _Allocator>
-_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
-operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs);
-#endif
-
template <class _CharT, class _Traits, class _Allocator>
class basic_string {
private:
More information about the libcxx-commits
mailing list