[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
Sun Jul 14 07:19:01 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 01/20] [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 3197d2cd1b271..0b8abe38e8bd7 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 81c05b9112bd2..6fbac70593cc0 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 fa11da62bc080..8793d9385b79a 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 a456f8cb80ee3..7758a4ae42e04 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 0ed77345baa71..d7e98fdb47208 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 8d944a194faf4..4fb733716b99e 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 a86ab2adff6a9..f3c70cf977973 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 3ec548f56cea1..35bbfd916ac80 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 0000000000000..efa57442997e7
--- /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 f2b8d55c0e11b..1afdb6475b187 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 02/20] 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 7758a4ae42e04..eb5f2b78af082 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 efa57442997e7..21936d76d0632 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 1afdb6475b187..1b938fa30c59d 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 03/20] 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 21936d76d0632..f2fb1dbe7195d 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 04/20] Restored formatting
---
libcxx/include/string | 44 +++++++++++++++++++++----------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index eb5f2b78af082..5af81486fa30d 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 05/20] 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 5af81486fa30d..bd648a33b5cdd 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 f2fb1dbe7195d..2d0981ed450be 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 06/20] 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 2d0981ed450be..7f08d460a6fb1 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 07/20] 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 bd648a33b5cdd..2a8cbb0b49072 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 7f08d460a6fb1..28a14950eef0a 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 08/20] 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 2a8cbb0b49072..a2606b73d5e57 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 28a14950eef0a..7efaa1125efb0 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 09/20] 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 fd6d894d0f63e..65968d78163a2 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:
>From 694e6fdbd767d53c8634a6aa9e3861b686e1a242 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 9 May 2024 20:01:17 +0300
Subject: [PATCH 10/20] Fixed rvalue argument overload
---
libcxx/include/string | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 072e039b4bd6d..5d2f3aff35195 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -4120,17 +4120,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>;
- 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;
+ __rhs.insert(0, __lhs);
+ return std::move(__rhs);
}
#endif // _LIBCPP_STD_VER >= 26
>From be56164074ad254a3db80a7eeee9a33a616c1230 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 10 May 2024 08:44:25 +0300
Subject: [PATCH 11/20] Workaround for `constexpr_char_traits` not compatible
with literals
---
.../string_op+/string.string_view.pass.cpp | 22 ++++++++++---------
1 file changed, 12 insertions(+), 10 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 7efaa1125efb0..f0ee9e58a59d2 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
@@ -91,7 +91,8 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + const string&
{
- std::basic_string_view<CharT, TraitsT> sv{x};
+ std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
+ std::basic_string_view<CharT, TraitsT> sv{st_};
const std::basic_string<CharT, TraitsT, AllocT> st{y, allocator};
std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = sv + st;
@@ -101,7 +102,8 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + string&&
{
- std::basic_string_view<CharT, TraitsT> sv{x};
+ std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
+ std::basic_string_view<CharT, TraitsT> sv{st_};
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);
@@ -152,18 +154,18 @@ constexpr bool test() {
int main(int, char**) {
test<char>();
static_assert(test<char>());
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ #ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t>();
- static_assert(test<wchar_t>());
-#endif
-#ifndef TEST_HAS_NO_CHAR8_T
+ static_assert(test<wchar_t>());
+ #endif
+ #ifndef TEST_HAS_NO_CHAR8_T
test<char8_t>();
- static_assert(test<char8_t>());
-#endif
+ static_assert(test<char8_t>());
+ #endif
test<char16_t>();
- static_assert(test<char16_t>());
+ static_assert(test<char16_t>());
test<char32_t>();
- static_assert(test<char32_t>());
+ static_assert(test<char32_t>());
return 0;
}
>From 20b9120dcb071cb2b46c191052965b379ca4b6f0 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 10 May 2024 08:45:50 +0300
Subject: [PATCH 12/20] Minor cleanup
---
.../string.nonmembers/string_op+/string.string_view.pass.cpp | 3 +--
1 file changed, 1 insertion(+), 2 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 f0ee9e58a59d2..3c146484ed5b5 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
@@ -91,8 +91,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + const string&
{
- std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
- std::basic_string_view<CharT, TraitsT> sv{st_};
+ 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;
>From a8c28fbfc83af1bc7cb6cd4ceeb1e6b4906e1a05 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 10 May 2024 08:48:30 +0300
Subject: [PATCH 13/20] Fixed formatting
---
.../string_op+/string.string_view.pass.cpp | 16 ++++++++--------
1 file changed, 8 insertions(+), 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 3c146484ed5b5..e5624e265042a 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
@@ -153,18 +153,18 @@ constexpr bool test() {
int main(int, char**) {
test<char>();
static_assert(test<char>());
- #ifndef TEST_HAS_NO_WIDE_CHARACTERS
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
test<wchar_t>();
- static_assert(test<wchar_t>());
- #endif
- #ifndef TEST_HAS_NO_CHAR8_T
+ static_assert(test<wchar_t>());
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
test<char8_t>();
- static_assert(test<char8_t>());
- #endif
+ static_assert(test<char8_t>());
+#endif
test<char16_t>();
- static_assert(test<char16_t>());
+ static_assert(test<char16_t>());
test<char32_t>();
- static_assert(test<char32_t>());
+ static_assert(test<char32_t>());
return 0;
}
>From bdbaf38a56b9958238ab292362f5f8c2cc17d274 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 10 May 2024 09:39:42 +0300
Subject: [PATCH 14/20] Cleanup
---
libcxx/include/string | 5 -----
1 file changed, 5 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 5d2f3aff35195..1eddb9f9a507f 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -717,10 +717,6 @@ _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+
@@ -2205,7 +2201,6 @@ private:
#if _LIBCPP_STD_VER >= 26
friend constexpr basic_string operator+ <>(const 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
};
>From 9f27ece1a6cf29b469db0b55b2975680f7c5f589 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 10 May 2024 15:26:46 +0300
Subject: [PATCH 15/20] Try to fix ASAN tests
---
.../string.nonmembers/string_op+/string.string_view.pass.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 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 e5624e265042a..c1a3b34e2557f 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
@@ -77,7 +77,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
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));
+ LIBCPP_ASSERT(is_string_asan_correct(std::move(st) + sv));
}
// string_view + string&
{
@@ -108,7 +108,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
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));
+ LIBCPP_ASSERT(is_string_asan_correct(sv + std::move(st)));
}
}
>From d56da5f1ef690bf9b117ca1a3d808df5a896c9b0 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 16 May 2024 21:19:58 +0300
Subject: [PATCH 16/20] Add a workaround note
---
.../string.nonmembers/string_op+/string.string_view.pass.cpp | 3 +++
1 file changed, 3 insertions(+)
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 c1a3b34e2557f..58c3b0bf7f163 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
@@ -101,6 +101,9 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + string&&
{
+ // Create a `basic_string` to workaround clang bug:
+ // https://github.com/llvm/llvm-project/issues/92382
+ // Comparison between pointers to a string literal and some other object results in constant evaluation failure.
std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
std::basic_string_view<CharT, TraitsT> sv{st_};
std::basic_string<CharT, TraitsT, AllocT> st{y, allocator};
>From da99993e40ee4672f2b6bd7f3c1ee03693262742 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Wed, 10 Jul 2024 22:53:52 +0300
Subject: [PATCH 17/20] Fixed formatting
---
libcxx/include/string | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/libcxx/include/string b/libcxx/include/string
index 6f56d381759da..2cc3cccc11c98 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -4049,17 +4049,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) {
- 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;
+ 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>
>From a7bf9a03d2327000cd11f9e258de1af6ea98cbb7 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 14 Jul 2024 15:34:50 +0300
Subject: [PATCH 18/20] WIP - tests with convertible to `string_view`
---
.../string_op+/string.string_view.pass.cpp | 157 ++++++++++++++++--
1 file changed, 145 insertions(+), 12 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 58c3b0bf7f163..e5ccb5153cf44 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
@@ -41,6 +41,58 @@
#include "test_allocator.h"
#include "test_macros.h"
+template <typename CharT, class Traits = std::char_traits<CharT>>
+class ConstConvertibleStringView {
+public:
+ constexpr explicit ConstConvertibleStringView(const CharT* cs) : cs_{cs} {}
+
+ constexpr operator std::basic_string_view<CharT, Traits>() = delete;
+ constexpr operator std::basic_string_view<CharT, Traits>() const { return std::basic_string_view<CharT, Traits>(cs_); }
+
+private:
+ const CharT* cs_;
+};
+
+static_assert(!std::constructible_from<std::basic_string_view<char>, ConstConvertibleStringView<char>>);
+static_assert(!std::convertible_to<ConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+static_assert(std::constructible_from<std::basic_string_view<char>, const ConstConvertibleStringView<char>>);
+static_assert(std::convertible_to<const ConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, ConstConvertibleStringView<wchar_t>>);
+static_assert(!std::convertible_to<ConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+
+static_assert(std::constructible_from<std::basic_string_view<wchar_t>, const ConstConvertibleStringView<wchar_t>>);
+static_assert(std::convertible_to<const ConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+#endif
+
+template <typename CharT, class Traits = std::char_traits<CharT>>
+class NonConstConvertibleStringView {
+public:
+ constexpr explicit NonConstConvertibleStringView(const CharT* cs) : cs_{cs} {}
+
+ constexpr operator std::basic_string_view<CharT, Traits>() { return std::basic_string_view<CharT, Traits>(cs_); }
+ constexpr operator std::basic_string_view<CharT, Traits>() const = delete;
+
+private:
+ const CharT* cs_;
+};
+
+static_assert(std::constructible_from<std::basic_string_view<char>, NonConstConvertibleStringView<char>>);
+static_assert(std::convertible_to<NonConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+static_assert(!std::constructible_from<std::basic_string_view<char>, const NonConstConvertibleStringView<char>>);
+static_assert(!std::convertible_to<const NonConstConvertibleStringView<char>, std::basic_string_view<char>>);
+
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+static_assert(std::constructible_from<std::basic_string_view<wchar_t>, NonConstConvertibleStringView<wchar_t>>);
+static_assert(std::convertible_to<NonConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+
+static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, const NonConstConvertibleStringView<wchar_t>>);
+static_assert(!std::convertible_to<const NonConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+#endif
+
#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))
@@ -113,6 +165,17 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
assert(result.get_allocator() == allocator);
LIBCPP_ASSERT(is_string_asan_correct(sv + std::move(st)));
}
+
+ // string& + nonconst_convertible_to_string_view
+ {
+ std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ NonConstConvertibleStringView<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));
+ }
}
template <typename CharT, typename TraitsT, typename AllocT = std::allocator<CharT>>
@@ -153,21 +216,91 @@ constexpr bool test() {
return true;
}
+template<typename CharT>
+constexpr bool test_const_convertible() {
+
+ // string& + const_convertible_to_string_view
+ {
+ std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ ConstConvertibleStringView<CharT, TraitsT> sv{y};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + std::as_const(sv);
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(st + std::as_const(sv)));
+ }
+ // const string& + const_convertible_to_string_view
+ {
+ const std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ ConstConvertibleStringView<CharT, TraitsT> sv{y};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + std::as_const(sv);
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(st + std::as_const(sv)));
+ }
+ // string&& + const_convertible_to_string_view
+ {
+ std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ ConstConvertibleStringView<CharT, TraitsT> sv{y};
+
+ std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = std::move(st) + std::as_const(sv);
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(std::move(st) + std::as_const(sv)));
+ }
+ // const_convertible_to_string_view + string&
+ {
+ ConstConvertibleStringView<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 = std::as_const(sv) + st;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(std::as_const(sv) + st));
+ }
+ // const_convertible_to_string_view + const string&
+ {
+ ConstConvertibleStringView<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 = std::as_const(sv) + st;
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(std::as_const(sv) + st));
+ }
+ // const_convertible_to_string_view + string&&
+ {
+ // // Create a `basic_string` to workaround clang bug:
+ // // https://github.com/llvm/llvm-project/issues/92382
+ // // Comparison between pointers to a string literal and some other object results in constant evaluation failure.
+ std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
+ ConstConvertibleStringView<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 = std::as_const(sv) + std::move(st);
+ assert(result == expected);
+ assert(result.get_allocator() == allocator);
+ LIBCPP_ASSERT(is_string_asan_correct(std::as_const(sv) + std::move(st)));
+ }
+
+}
+
int main(int, char**) {
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>());
+// #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 d214ef1055b366633ddb1945c9466d2603424d69 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 14 Jul 2024 17:15:36 +0300
Subject: [PATCH 19/20] Added ConvertibleToStringView test
---
.../string_op+/string.string_view.pass.cpp | 287 +++++++-----------
1 file changed, 115 insertions(+), 172 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 e5ccb5153cf44..3b18b5f84ca1a 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
@@ -41,70 +41,62 @@
#include "test_allocator.h"
#include "test_macros.h"
-template <typename CharT, class Traits = std::char_traits<CharT>>
-class ConstConvertibleStringView {
+template <typename CharT, class TraitsT = std::char_traits<CharT>>
+class ConvertibleToStringView {
public:
- constexpr explicit ConstConvertibleStringView(const CharT* cs) : cs_{cs} {}
+ constexpr explicit ConvertibleToStringView(const CharT* cs) : cs_{cs} {}
+ // template <typename AllocT>
+ // constexpr explicit ConvertibleToStringView(std::basic_string<CharT, TraitsT, AllocT> str) : cs_{str.c_str()} {}
- constexpr operator std::basic_string_view<CharT, Traits>() = delete;
- constexpr operator std::basic_string_view<CharT, Traits>() const { return std::basic_string_view<CharT, Traits>(cs_); }
+ constexpr operator std::basic_string_view<CharT, TraitsT>() { return std::basic_string_view<CharT, TraitsT>(cs_); }
+ constexpr operator std::basic_string_view<CharT, TraitsT>() const {
+ return std::basic_string_view<CharT, TraitsT>(cs_);
+ }
private:
const CharT* cs_;
};
-static_assert(!std::constructible_from<std::basic_string_view<char>, ConstConvertibleStringView<char>>);
-static_assert(!std::convertible_to<ConstConvertibleStringView<char>, std::basic_string_view<char>>);
-
-static_assert(std::constructible_from<std::basic_string_view<char>, const ConstConvertibleStringView<char>>);
-static_assert(std::convertible_to<const ConstConvertibleStringView<char>, std::basic_string_view<char>>);
-
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, ConstConvertibleStringView<wchar_t>>);
-static_assert(!std::convertible_to<ConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-
-static_assert(std::constructible_from<std::basic_string_view<wchar_t>, const ConstConvertibleStringView<wchar_t>>);
-static_assert(std::convertible_to<const ConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-#endif
+// static_assert(!std::constructible_from<std::basic_string_view<char>, ConvertibleToStringView<char>>);
+// static_assert(!std::convertible_to<ConvertibleToStringView<char>, std::basic_string_view<char>>);
-template <typename CharT, class Traits = std::char_traits<CharT>>
-class NonConstConvertibleStringView {
-public:
- constexpr explicit NonConstConvertibleStringView(const CharT* cs) : cs_{cs} {}
+static_assert(std::constructible_from<std::basic_string_view<char>, const ConvertibleToStringView<char>>);
+static_assert(std::convertible_to<const ConvertibleToStringView<char>, std::basic_string_view<char>>);
- constexpr operator std::basic_string_view<CharT, Traits>() { return std::basic_string_view<CharT, Traits>(cs_); }
- constexpr operator std::basic_string_view<CharT, Traits>() const = delete;
+// #ifndef TEST_HAS_NO_WIDE_CHARACTERS
+// static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, ConvertibleToStringView<wchar_t>>);
+// static_assert(!std::convertible_to<ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-private:
- const CharT* cs_;
-};
+// static_assert(std::constructible_from<std::basic_string_view<wchar_t>, const ConvertibleToStringView<wchar_t>>);
+// static_assert(std::convertible_to<const ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+// #endif
-static_assert(std::constructible_from<std::basic_string_view<char>, NonConstConvertibleStringView<char>>);
-static_assert(std::convertible_to<NonConstConvertibleStringView<char>, std::basic_string_view<char>>);
+static_assert(std::constructible_from<std::basic_string_view<char>, ConvertibleToStringView<char>>);
+static_assert(std::convertible_to<ConvertibleToStringView<char>, std::basic_string_view<char>>);
-static_assert(!std::constructible_from<std::basic_string_view<char>, const NonConstConvertibleStringView<char>>);
-static_assert(!std::convertible_to<const NonConstConvertibleStringView<char>, std::basic_string_view<char>>);
+// static_assert(!std::constructible_from<std::basic_string_view<char>, const ConvertibleToStringView<char>>);
+// static_assert(!std::convertible_to<const ConvertibleToStringView<char>, std::basic_string_view<char>>);
-#ifndef TEST_HAS_NO_WIDE_CHARACTERS
-static_assert(std::constructible_from<std::basic_string_view<wchar_t>, NonConstConvertibleStringView<wchar_t>>);
-static_assert(std::convertible_to<NonConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+// #ifndef TEST_HAS_NO_WIDE_CHARACTERS
+// static_assert(std::constructible_from<std::basic_string_view<wchar_t>, ConvertibleToStringView<wchar_t>>);
+// static_assert(std::convertible_to<ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, const NonConstConvertibleStringView<wchar_t>>);
-static_assert(!std::convertible_to<const NonConstConvertibleStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-#endif
+// static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, const ConvertibleToStringView<wchar_t>>);
+// static_assert(!std::convertible_to<const ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
+// #endif
#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))
+// #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>
+template <template <typename, typename> typename StringViewT, typename CharT, typename TraitsT, typename AllocT>
constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
AllocT allocator;
// string& + string_view
{
std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- std::basic_string_view<CharT, TraitsT> sv{y};
+ StringViewT<CharT, TraitsT> sv{y};
std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + sv;
assert(result == expected);
@@ -114,7 +106,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
// const string& + string_view
{
const std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- std::basic_string_view<CharT, TraitsT> sv{y};
+ StringViewT<CharT, TraitsT> sv{y};
std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + sv;
assert(result == expected);
@@ -124,7 +116,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
// string&& + string_view
{
std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- std::basic_string_view<CharT, TraitsT> sv{y};
+ StringViewT<CharT, TraitsT> sv{y};
std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = std::move(st) + sv;
assert(result == expected);
@@ -133,7 +125,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + string&
{
- std::basic_string_view<CharT, TraitsT> sv{x};
+ StringViewT<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;
@@ -143,7 +135,7 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + const string&
{
- std::basic_string_view<CharT, TraitsT> sv{x};
+ StringViewT<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;
@@ -153,154 +145,105 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
}
// string_view + string&&
{
- // Create a `basic_string` to workaround clang bug:
+ // TODO: Create a `basic_string` to workaround clang bug:
// https://github.com/llvm/llvm-project/issues/92382
// Comparison between pointers to a string literal and some other object results in constant evaluation failure.
- std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
- std::basic_string_view<CharT, TraitsT> sv{st_};
- 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 + std::move(st)));
- }
-
- // string& + nonconst_convertible_to_string_view
- {
- std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- NonConstConvertibleStringView<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));
+ if constexpr (std::same_as<StringViewT<CharT, TraitsT>, std::basic_string_view<CharT, TraitsT>>) {
+ std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
+ StringViewT<CharT, TraitsT> sv{st_};
+ // StringViewT<CharT, TraitsT> sv = [&] {
+ // if constexpr (std::same_as<StringViewT<CharT, TraitsT>, std::basic_string_view<CharT, TraitsT>>) {
+ // std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
+ // return std::basic_string_view<CharT, TraitsT>{st};
+ // } else {
+ // return StringViewT<CharT, TraitsT>{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 + std::move(st)));
+ }
}
}
-template <typename CharT, typename TraitsT, typename AllocT = std::allocator<CharT>>
+template <template <typename, typename> typename StringViewT,
+ typename CharT,
+ typename TraitsT,
+ typename AllocT = std::allocator<CharT>>
constexpr void test() {
// 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"));
- 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"));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS(""), CS(""), CS(""));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS(""), CS("short"), CS("short"));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS(""), CS("not so short"), CS("not so short"));
+ test<StringViewT, CharT, TraitsT, AllocT>(
+ CS(""), CS("this is a much longer string"), CS("this is a much longer string"));
+
+ test<StringViewT, CharT, TraitsT, AllocT>(CS(""), CS(""), CS(""));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS("short"), CS(""), CS("short"));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS("not so short"), CS(""), CS("not so short"));
+ test<StringViewT, 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>(
+ test<StringViewT, CharT, TraitsT, AllocT>(CS("B"), CS("D"), CS("BD"));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS("zmt94"), CS("+hkt82"), CS("zmt94+hkt82"));
+ test<StringViewT, CharT, TraitsT, AllocT>(CS("not so short"), CS("+is not bad"), CS("not so short+is not bad"));
+ test<StringViewT, 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"));
}
-template <typename CharT>
+template <template <typename, typename> typename StringViewT, typename CharT>
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<StringViewT, CharT, std::char_traits<CharT>>();
+ test<StringViewT, CharT, std::char_traits<CharT>, min_allocator<CharT>>();
+ test<StringViewT, CharT, std::char_traits<CharT>, safe_allocator<CharT>>();
+ test<StringViewT, 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>>();
+ test<StringViewT, CharT, constexpr_char_traits<CharT>>();
+ test<StringViewT, CharT, constexpr_char_traits<CharT>, min_allocator<CharT>>();
+ test<StringViewT, CharT, constexpr_char_traits<CharT>, safe_allocator<CharT>>();
+ test<StringViewT, CharT, constexpr_char_traits<CharT>, test_allocator<CharT>>();
return true;
}
-template<typename CharT>
-constexpr bool test_const_convertible() {
-
- // string& + const_convertible_to_string_view
- {
- std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- ConstConvertibleStringView<CharT, TraitsT> sv{y};
-
- std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + std::as_const(sv);
- assert(result == expected);
- assert(result.get_allocator() == allocator);
- LIBCPP_ASSERT(is_string_asan_correct(st + std::as_const(sv)));
- }
- // const string& + const_convertible_to_string_view
- {
- const std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- ConstConvertibleStringView<CharT, TraitsT> sv{y};
-
- std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = st + std::as_const(sv);
- assert(result == expected);
- assert(result.get_allocator() == allocator);
- LIBCPP_ASSERT(is_string_asan_correct(st + std::as_const(sv)));
- }
- // string&& + const_convertible_to_string_view
- {
- std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- ConstConvertibleStringView<CharT, TraitsT> sv{y};
-
- std::same_as<std::basic_string<CharT, TraitsT, AllocT>> decltype(auto) result = std::move(st) + std::as_const(sv);
- assert(result == expected);
- assert(result.get_allocator() == allocator);
- LIBCPP_ASSERT(is_string_asan_correct(std::move(st) + std::as_const(sv)));
- }
- // const_convertible_to_string_view + string&
- {
- ConstConvertibleStringView<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 = std::as_const(sv) + st;
- assert(result == expected);
- assert(result.get_allocator() == allocator);
- LIBCPP_ASSERT(is_string_asan_correct(std::as_const(sv) + st));
- }
- // const_convertible_to_string_view + const string&
- {
- ConstConvertibleStringView<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 = std::as_const(sv) + st;
- assert(result == expected);
- assert(result.get_allocator() == allocator);
- LIBCPP_ASSERT(is_string_asan_correct(std::as_const(sv) + st));
- }
- // const_convertible_to_string_view + string&&
- {
- // // Create a `basic_string` to workaround clang bug:
- // // https://github.com/llvm/llvm-project/issues/92382
- // // Comparison between pointers to a string literal and some other object results in constant evaluation failure.
- std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
- ConstConvertibleStringView<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 = std::as_const(sv) + std::move(st);
- assert(result == expected);
- assert(result.get_allocator() == allocator);
- LIBCPP_ASSERT(is_string_asan_correct(std::as_const(sv) + std::move(st)));
- }
-
-}
-
int main(int, char**) {
- 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>());
+ // std::basic_string_view
+ test<std::basic_string_view, char>();
+ static_assert(test<std::basic_string_view, char>());
+#ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test<std::basic_string_view, wchar_t>();
+ static_assert(test<std::basic_string_view, wchar_t>());
+#endif
+#ifndef TEST_HAS_NO_CHAR8_T
+ test<std::basic_string_view, char8_t>();
+ static_assert(test<std::basic_string_view, char8_t>());
+#endif
+ test<std::basic_string_view, char16_t>();
+ static_assert(test<std::basic_string_view, char16_t>());
+ test<std::basic_string_view, char32_t>();
+ static_assert(test<std::basic_string_view, char32_t>());
+
+ // ConvertibleToStringView
+ test<ConvertibleToStringView, char>();
+ static_assert(test<ConvertibleToStringView, char>());
+ #ifndef TEST_HAS_NO_WIDE_CHARACTERS
+ test<ConvertibleToStringView, wchar_t>();
+ static_assert(test<ConvertibleToStringView, wchar_t>());
+ #endif
+ #ifndef TEST_HAS_NO_CHAR8_T
+ test<ConvertibleToStringView, char8_t>();
+ static_assert(test<ConvertibleToStringView, char8_t>());
+ #endif
+ test<ConvertibleToStringView, char16_t>();
+ static_assert(test<ConvertibleToStringView, char16_t>());
+ test<ConvertibleToStringView, char32_t>();
+ static_assert(test<ConvertibleToStringView, char32_t>());
return 0;
}
>From 20f39e114f9e1ef0d838d0b118c6658ced9e9fbe Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 14 Jul 2024 17:18:36 +0300
Subject: [PATCH 20/20] Cleanup
---
.../string_op+/string.string_view.pass.cpp | 34 -------------------
1 file changed, 34 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 3b18b5f84ca1a..4ca3688c31e29 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
@@ -45,8 +45,6 @@ template <typename CharT, class TraitsT = std::char_traits<CharT>>
class ConvertibleToStringView {
public:
constexpr explicit ConvertibleToStringView(const CharT* cs) : cs_{cs} {}
- // template <typename AllocT>
- // constexpr explicit ConvertibleToStringView(std::basic_string<CharT, TraitsT, AllocT> str) : cs_{str.c_str()} {}
constexpr operator std::basic_string_view<CharT, TraitsT>() { return std::basic_string_view<CharT, TraitsT>(cs_); }
constexpr operator std::basic_string_view<CharT, TraitsT>() const {
@@ -57,37 +55,13 @@ class ConvertibleToStringView {
const CharT* cs_;
};
-// static_assert(!std::constructible_from<std::basic_string_view<char>, ConvertibleToStringView<char>>);
-// static_assert(!std::convertible_to<ConvertibleToStringView<char>, std::basic_string_view<char>>);
-
static_assert(std::constructible_from<std::basic_string_view<char>, const ConvertibleToStringView<char>>);
static_assert(std::convertible_to<const ConvertibleToStringView<char>, std::basic_string_view<char>>);
-// #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-// static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, ConvertibleToStringView<wchar_t>>);
-// static_assert(!std::convertible_to<ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-
-// static_assert(std::constructible_from<std::basic_string_view<wchar_t>, const ConvertibleToStringView<wchar_t>>);
-// static_assert(std::convertible_to<const ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-// #endif
-
static_assert(std::constructible_from<std::basic_string_view<char>, ConvertibleToStringView<char>>);
static_assert(std::convertible_to<ConvertibleToStringView<char>, std::basic_string_view<char>>);
-// static_assert(!std::constructible_from<std::basic_string_view<char>, const ConvertibleToStringView<char>>);
-// static_assert(!std::convertible_to<const ConvertibleToStringView<char>, std::basic_string_view<char>>);
-
-// #ifndef TEST_HAS_NO_WIDE_CHARACTERS
-// static_assert(std::constructible_from<std::basic_string_view<wchar_t>, ConvertibleToStringView<wchar_t>>);
-// static_assert(std::convertible_to<ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-
-// static_assert(!std::constructible_from<std::basic_string_view<wchar_t>, const ConvertibleToStringView<wchar_t>>);
-// static_assert(!std::convertible_to<const ConvertibleToStringView<wchar_t>, std::basic_string_view<wchar_t>>);
-// #endif
-
#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 <template <typename, typename> typename StringViewT, typename CharT, typename TraitsT, typename AllocT>
constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
@@ -151,14 +125,6 @@ constexpr void test(const CharT* x, const CharT* y, const CharT* expected) {
if constexpr (std::same_as<StringViewT<CharT, TraitsT>, std::basic_string_view<CharT, TraitsT>>) {
std::basic_string<CharT, TraitsT, AllocT> st_{x, allocator};
StringViewT<CharT, TraitsT> sv{st_};
- // StringViewT<CharT, TraitsT> sv = [&] {
- // if constexpr (std::same_as<StringViewT<CharT, TraitsT>, std::basic_string_view<CharT, TraitsT>>) {
- // std::basic_string<CharT, TraitsT, AllocT> st{x, allocator};
- // return std::basic_string_view<CharT, TraitsT>{st};
- // } else {
- // return StringViewT<CharT, TraitsT>{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);
More information about the libcxx-commits
mailing list