Skip to content

Commit 4a19be5

Browse files
H-G-HristovZingam
andauthored
[libc++][strings] P2591R5: Concatenation of strings and string views (#88389)
Implemented: https://wg21.link/P2591R5 - https://eel.is/c++draft/string.syn - https://eel.is/c++draft/string.op.plus --------- Co-authored-by: Hristo Hristov <[email protected]>
1 parent da0c8b2 commit 4a19be5

File tree

10 files changed

+332
-9
lines changed

10 files changed

+332
-9
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,8 @@ Status
474474
---------------------------------------------------------- -----------------
475475
``__cpp_lib_sstream_from_string_view`` ``202306L``
476476
---------------------------------------------------------- -----------------
477+
``__cpp_lib_string_view`` ``202403L``
478+
---------------------------------------------------------- -----------------
477479
``__cpp_lib_submdspan`` *unimplemented*
478480
---------------------------------------------------------- -----------------
479481
``__cpp_lib_text_encoding`` *unimplemented*

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ Implemented Papers
4646
- P2872R3 - Remove ``wstring_convert`` From C++26
4747
- P3142R0 - Printing Blank Lines with ``println`` (as DR against C++23)
4848
- P2944R3 - Comparisons for ``reference_wrapper`` (comparison operators for ``reference_wrapper`` only)
49+
- P2591R5 - Concatenation of strings and string views
4950
- P2968R2 - Make ``std::ignore`` a first-class object
5051
- P2302R4 - ``std::ranges::contains``
5152
- P1659R3 - ``std::ranges::starts_with`` and ``std::ranges::ends_with``

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"`P2845R8 <https://wg21.link/P2845R8>`__","LWG","Formatting of ``std::filesystem::path``","Tokyo March 2024","","","|format|"
5656
"`P0493R5 <https://wg21.link/P0493R5>`__","LWG","Atomic minimum/maximum","Tokyo March 2024","","",""
5757
"`P2542R8 <https://wg21.link/P2542R8>`__","LWG","``views::concat``","Tokyo March 2024","","","|ranges|"
58-
"`P2591R5 <https://wg21.link/P2591R5>`__","LWG","Concatenation of strings and string views","Tokyo March 2024","","",""
58+
"`P2591R5 <https://wg21.link/P2591R5>`__","LWG","Concatenation of strings and string views","Tokyo March 2024","|Complete|","19.0",""
5959
"`P2248R8 <https://wg21.link/P2248R8>`__","LWG","Enabling list-initialization for algorithms","Tokyo March 2024","","",""
6060
"`P2810R4 <https://wg21.link/P2810R4>`__","LWG","``is_debugger_present`` ``is_replaceable``","Tokyo March 2024","","",""
6161
"`P1068R11 <https://wg21.link/P1068R11>`__","LWG","Vector API for random number generation","Tokyo March 2024","","",""

libcxx/include/string

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,24 @@ template<class charT, class traits, class Allocator>
407407
basic_string<charT, traits, Allocator>
408408
operator+(const basic_string<charT, traits, Allocator>& lhs, charT rhs); // constexpr since C++20
409409
410+
template<class charT, class traits, class Allocator>
411+
constexpr basic_string<charT, traits, Allocator>
412+
operator+(const basic_string<charT, traits, Allocator>& lhs,
413+
type_identity_t<basic_string_view<charT, traits>> rhs); // Since C++26
414+
template<class charT, class traits, class Allocator>
415+
constexpr basic_string<charT, traits, Allocator>
416+
operator+(basic_string<charT, traits, Allocator>&& lhs,
417+
type_identity_t<basic_string_view<charT, traits>> rhs); // Since C++26
418+
template<class charT, class traits, class Allocator>
419+
constexpr basic_string<charT, traits, Allocator>
420+
operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
421+
const basic_string<charT, traits, Allocator>& rhs); // Since C++26
422+
template<class charT, class traits, class Allocator>
423+
constexpr basic_string<charT, traits, Allocator>
424+
operator+(type_identity_t<basic_string_view<charT, traits>> lhs,
425+
basic_string<charT, traits, Allocator>&& rhs); // Since C++26
426+
427+
410428
template<class charT, class traits, class Allocator>
411429
bool operator==(const basic_string<charT, traits, Allocator>& lhs,
412430
const basic_string<charT, traits, Allocator>& rhs) noexcept; // constexpr since C++20
@@ -687,6 +705,28 @@ template <class _CharT, class _Traits, class _Allocator>
687705
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string<_CharT, _Traits, _Allocator>
688706
operator+(const basic_string<_CharT, _Traits, _Allocator>& __x, _CharT __y);
689707

708+
#if _LIBCPP_STD_VER >= 26
709+
710+
template <class _CharT, class _Traits, class _Allocator>
711+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
712+
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
713+
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
714+
715+
template <class _CharT, class _Traits, class _Allocator>
716+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
717+
operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, type_identity_t<basic_string_view<_CharT, _Traits>> __rhs);
718+
719+
template <class _CharT, class _Traits, class _Allocator>
720+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
721+
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
722+
const basic_string<_CharT, _Traits, _Allocator>& __rhs);
723+
724+
template <class _CharT, class _Traits, class _Allocator>
725+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
726+
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs);
727+
728+
#endif
729+
690730
extern template _LIBCPP_EXPORTED_FROM_ABI string operator+
691731
<char, char_traits<char>, allocator<char> >(char const*, string const&);
692732

@@ -2150,6 +2190,10 @@ private:
21502190
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(value_type, const basic_string&);
21512191
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, const value_type*);
21522192
friend _LIBCPP_CONSTEXPR_SINCE_CXX20 basic_string operator+ <>(const basic_string&, value_type);
2193+
#if _LIBCPP_STD_VER >= 26
2194+
friend constexpr basic_string operator+ <>(const basic_string&, type_identity_t<__self_view>);
2195+
friend constexpr basic_string operator+ <>(type_identity_t<__self_view>, const basic_string&);
2196+
#endif
21532197
};
21542198

21552199
// These declarations must appear before any functions are implicitly used
@@ -4007,6 +4051,60 @@ operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, _CharT __rhs) {
40074051

40084052
#endif // _LIBCPP_CXX03_LANG
40094053

4054+
#if _LIBCPP_STD_VER >= 26
4055+
4056+
template <class _CharT, class _Traits, class _Allocator>
4057+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
4058+
operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs,
4059+
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) {
4060+
using _String = basic_string<_CharT, _Traits, _Allocator>;
4061+
typename _String::size_type __lhs_sz = __lhs.size();
4062+
typename _String::size_type __rhs_sz = __rhs.size();
4063+
_String __r(__uninitialized_size_tag(),
4064+
__lhs_sz + __rhs_sz,
4065+
_String::__alloc_traits::select_on_container_copy_construction(__lhs.get_allocator()));
4066+
auto __ptr = std::__to_address(__r.__get_pointer());
4067+
_Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4068+
_Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
4069+
_Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4070+
return __r;
4071+
}
4072+
4073+
template <class _CharT, class _Traits, class _Allocator>
4074+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
4075+
operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs,
4076+
type_identity_t<basic_string_view<_CharT, _Traits>> __rhs) {
4077+
__lhs.append(__rhs);
4078+
return std::move(__lhs);
4079+
}
4080+
4081+
template <class _CharT, class _Traits, class _Allocator>
4082+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
4083+
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
4084+
const basic_string<_CharT, _Traits, _Allocator>& __rhs) {
4085+
using _String = basic_string<_CharT, _Traits, _Allocator>;
4086+
typename _String::size_type __lhs_sz = __lhs.size();
4087+
typename _String::size_type __rhs_sz = __rhs.size();
4088+
_String __r(__uninitialized_size_tag(),
4089+
__lhs_sz + __rhs_sz,
4090+
_String::__alloc_traits::select_on_container_copy_construction(__rhs.get_allocator()));
4091+
auto __ptr = std::__to_address(__r.__get_pointer());
4092+
_Traits::copy(__ptr, __lhs.data(), __lhs_sz);
4093+
_Traits::copy(__ptr + __lhs_sz, __rhs.data(), __rhs_sz);
4094+
_Traits::assign(__ptr + __lhs_sz + __rhs_sz, 1, _CharT());
4095+
return __r;
4096+
}
4097+
4098+
template <class _CharT, class _Traits, class _Allocator>
4099+
_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator>
4100+
operator+(type_identity_t<basic_string_view<_CharT, _Traits>> __lhs,
4101+
basic_string<_CharT, _Traits, _Allocator>&& __rhs) {
4102+
__rhs.insert(0, __lhs);
4103+
return std::move(__rhs);
4104+
}
4105+
4106+
#endif // _LIBCPP_STD_VER >= 26
4107+
40104108
// swap
40114109

40124110
template <class _CharT, class _Traits, class _Allocator>

libcxx/include/version

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,8 @@ __cpp_lib_stdatomic_h 202011L <stdatomic.h>
231231
__cpp_lib_string_contains 202011L <string> <string_view>
232232
__cpp_lib_string_resize_and_overwrite 202110L <string>
233233
__cpp_lib_string_udls 201304L <string>
234-
__cpp_lib_string_view 201803L <string> <string_view>
234+
__cpp_lib_string_view 202403L <string> <string_view>
235+
201803L // C++20
235236
201606L // C++17
236237
__cpp_lib_submdspan 202306L <mdspan>
237238
__cpp_lib_syncbuf 201803L <syncstream>
@@ -547,6 +548,8 @@ __cpp_lib_void_t 201411L <type_traits>
547548
# define __cpp_lib_span_at 202311L
548549
# define __cpp_lib_span_initializer_list 202311L
549550
# define __cpp_lib_sstream_from_string_view 202306L
551+
# undef __cpp_lib_string_view
552+
# define __cpp_lib_string_view 202403L
550553
// # define __cpp_lib_submdspan 202306L
551554
// # define __cpp_lib_text_encoding 202306L
552555
# undef __cpp_lib_to_chars

libcxx/test/std/language.support/support.limits/support.limits.general/string.version.compile.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
__cpp_lib_string_udls 201304L [C++14]
3030
__cpp_lib_string_view 201606L [C++17]
3131
201803L [C++20]
32+
202403L [C++26]
3233
__cpp_lib_to_string 202306L [C++26]
3334
*/
3435

@@ -483,8 +484,8 @@
483484
# ifndef __cpp_lib_string_view
484485
# error "__cpp_lib_string_view should be defined in c++26"
485486
# endif
486-
# if __cpp_lib_string_view != 201803L
487-
# error "__cpp_lib_string_view should have the value 201803L in c++26"
487+
# if __cpp_lib_string_view != 202403L
488+
# error "__cpp_lib_string_view should have the value 202403L in c++26"
488489
# endif
489490

490491
# if !defined(_LIBCPP_VERSION)

libcxx/test/std/language.support/support.limits/support.limits.general/string_view.version.compile.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
__cpp_lib_string_contains 202011L [C++23]
2424
__cpp_lib_string_view 201606L [C++17]
2525
201803L [C++20]
26+
202403L [C++26]
2627
*/
2728

2829
#include <string_view>
@@ -252,8 +253,8 @@
252253
# ifndef __cpp_lib_string_view
253254
# error "__cpp_lib_string_view should be defined in c++26"
254255
# endif
255-
# if __cpp_lib_string_view != 201803L
256-
# error "__cpp_lib_string_view should have the value 201803L in c++26"
256+
# if __cpp_lib_string_view != 202403L
257+
# error "__cpp_lib_string_view should have the value 202403L in c++26"
257258
# endif
258259

259260
#endif // TEST_STD_VER > 23

libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@
216216
__cpp_lib_string_udls 201304L [C++14]
217217
__cpp_lib_string_view 201606L [C++17]
218218
201803L [C++20]
219+
202403L [C++26]
219220
__cpp_lib_submdspan 202306L [C++26]
220221
__cpp_lib_syncbuf 201803L [C++20]
221222
__cpp_lib_text_encoding 202306L [C++26]
@@ -7894,8 +7895,8 @@
78947895
# ifndef __cpp_lib_string_view
78957896
# error "__cpp_lib_string_view should be defined in c++26"
78967897
# endif
7897-
# if __cpp_lib_string_view != 201803L
7898-
# error "__cpp_lib_string_view should have the value 201803L in c++26"
7898+
# if __cpp_lib_string_view != 202403L
7899+
# error "__cpp_lib_string_view should have the value 202403L in c++26"
78997900
# endif
79007901

79017902
# if !defined(_LIBCPP_VERSION)

0 commit comments

Comments
 (0)