[libcxx-commits] [libcxx] [libc++][strings] P2591R5: Concatenation of strings and string views (PR #88389)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Tue Apr 16 00:05:11 PDT 2024


================
@@ -4003,6 +4044,69 @@ 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>;
+    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>
+_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>;
+  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;
+}
+
+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>;
+  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;
----------------
frederick-vs-ja wrote:

It's incorrect to me to use `select_on_container_copy_construction` in this rvalue overload. When the `basic_string` argument is an rvalue, the allocator of the result should be simply copy-constructed (or equivalently move-constructed, see also [LWG2593](https://cplusplus.github.io/LWG/issue2593)) from that of the rvalue argument.

I think the code shown in the paper is good enough for rvalue `basic_string` overloads. It has been already dynamically allocating at most once, and the allocation is unavoidable whenever the code performs. (Although the code shown for lvalue overloads may dynamically allocate twice, which should be avoided.)

WDYT? @mordante @hawkinsw 

https://github.com/llvm/llvm-project/pull/88389


More information about the libcxx-commits mailing list