[libcxx-commits] [libcxx] WIP - [libc++][strings] P2591R5: Concatenation of strings and string views (PR #88389)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Apr 11 06:11:38 PDT 2024
https://github.com/H-G-Hristov created https://github.com/llvm/llvm-project/pull/88389
Implemented: https://wg21.link/P2591R5
>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] [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"],
},
More information about the libcxx-commits
mailing list