From 2d606f402e34d446322c44598ada051c14fa6057 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 11 Apr 2024 10:28:35 +0300 Subject: [PATCH 01/22] [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 `__","LWG","Formatting of ``std::filesystem::path``","Tokyo March 2024","","","|format|" "`P0493R5 `__","LWG","Atomic minimum/maximum","Tokyo March 2024","","","" "`P2542R8 `__","LWG","``views::concat``","Tokyo March 2024","","","|ranges|" -"`P2591R5 `__","LWG","Concatenation of strings and string views","Tokyo March 2024","","","" +"`P2591R5 `__","LWG","Concatenation of strings and string views","Tokyo March 2024","|Complete|","19.0","" "`P2248R8 `__","LWG","Enabling list-initialization for algorithms","Tokyo March 2024","","","" "`P2810R4 `__","LWG","``is_debugger_present`` ``is_replaceable``","Tokyo March 2024","","","" "`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 basic_string operator+(const basic_string& lhs, charT rhs); // constexpr since C++20 +template + constexpr basic_string + operator+(const basic_string& lhs, + type_identity_t> rhs); // Since C++26 +template + constexpr basic_string + operator+(basic_string&& lhs, + type_identity_t> rhs); // Since C++26 +template + constexpr basic_string + operator+(type_identity_t> lhs, + const basic_string& rhs); // Since C++26 +template + constexpr basic_string + operator+(type_identity_t> lhs, + basic_string&& rhs); // Since C++26 + + template bool operator==(const basic_string& lhs, const basic_string& 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 = 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 ::__ template 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 +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, + type_identity_t> __rhs) { + using _String = basic_string<_CharT, _Traits, _Allocator>; + + _String __r = __lhs; + __r.append(__rhs); + return __r; +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, + type_identity_t> __rhs) { + __lhs.append(__rhs); + return std::move(__lhs); +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(type_identity_t> __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 +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(type_identity_t> __lhs, + basic_string<_CharT, _Traits, _Allocator>&& __rhs) { + __rhs.insert(0, __lhs); + return std::move(__rhs); +} + +#endif // _LIBCPP_STD_VER >= 26 + // swap template 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 __cpp_lib_string_contains 202011L __cpp_lib_string_resize_and_overwrite 202110L __cpp_lib_string_udls 201304L -__cpp_lib_string_view 201803L +__cpp_lib_string_view 202403L + 201803L // C++20 201606L // C++17 __cpp_lib_submdspan 202306L __cpp_lib_syncbuf 201803L @@ -530,6 +531,8 @@ __cpp_lib_within_lifetime 202306L # 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 @@ -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.op.plus] +// +// template +// constexpr basic_string +// operator+(const basic_string& lhs, +// type_identity_t> rhs); // Since C++26 +// template +// constexpr basic_string +// operator+(basic_string&& lhs, +// type_identity_t> rhs); // Since C++26 +// template +// constexpr basic_string +// operator+(type_identity_t> lhs, +// const basic_string& rhs); // Since C++26 +// template +// constexpr basic_string +// operator+(type_identity_t> lhs, +// basic_string&& rhs); // Since C++26 + +#include +#include +#include + +#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(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a) +#define SV(S) std::basic_string_view(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S)) + +template +constexpr void test() { + AllocT allocator; + std::basic_string st{ST("Hello", allocator)}; + std::basic_string_view sv{SV("World")}; + + assert(st + sv == ST("HelloWorld", allocator)); + assert(st + sv != ST("Hello World", allocator)); +} + +constexpr bool test() { + test, min_allocator>(); + test, min_allocator>(); + test, safe_allocator>(); + test, safe_allocator>(); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test, min_allocator>(); + test, min_allocator>(); + test, safe_allocator>(); + test, safe_allocator>(); +#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 Date: Thu, 11 Apr 2024 21:01:34 +0300 Subject: [PATCH 02/22] 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> __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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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&& rhs); // Since C++26 #include +#include #include #include @@ -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(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S)) template -constexpr void test() { +constexpr void test(const CharT* x, const CharT* y, const CharT* expected) { AllocT allocator; - std::basic_string st{ST("Hello", allocator)}; - std::basic_string_view sv{SV("World")}; - assert(st + sv == ST("HelloWorld", allocator)); - assert(st + sv != ST("Hello World", allocator)); + // string& + string_view + { + std::basic_string st{x, allocator}; + std::basic_string_view sv{y}; + + std::same_as> 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 st{x, allocator}; + std::basic_string_view sv{y}; + + std::same_as> 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 st{x, allocator}; + std::basic_string_view sv{y}; + + std::same_as> 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 sv{x}; + std::basic_string st{y, allocator}; + + std::same_as> 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 sv{x}; + const std::basic_string st{y, allocator}; + + std::same_as> 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 sv{x}; + std::basic_string st{y, allocator}; + + std::same_as> 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 AllocT = std::allocator> +constexpr void test() { + // Concatinate with an empty string + test(CS(""), CS(""), CS("")); + test(CS(""), CS("short"), CS("short")); + test(CS(""), CS("not so short"), CS("not so short")); + test(CS(""), CS("this is a much longer string"), CS("this is a much longer string")); + + test(CS(""), CS(""), CS("")); + test(CS("short"), CS(""), CS("short")); + test(CS("not so short"), CS(""), CS("not so short")); + test(CS("this is a much longer string"), CS(""), CS("this is a much longer string")); + + // Non empty + test(CS("B"), CS("D"), CS("BD")); + test(CS("zmt94"), CS("+hkt82"), CS("zmt94+hkt82")); + test(CS("not so short"), CS("+is not bad"), CS("not so short+is not bad")); + test( + 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>(); test, min_allocator>(); - test, min_allocator>(); test, safe_allocator>(); + // test, test_allocator>(); + + test>(); + test, min_allocator>(); test, safe_allocator>(); + // test, test_allocator>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS - test, min_allocator>(); - test, min_allocator>(); + test>(); + // test, min_allocator>(); test, safe_allocator>(); + // test, test_allocator>(); + + test>(); + // test, min_allocator>(); test, safe_allocator>(); + // test, test_allocator>(); #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 Date: Thu, 11 Apr 2024 21:03:43 +0300 Subject: [PATCH 03/22] 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 AllocT = std::allocator> constexpr void test() { - // Concatinate with an empty string + // Concatinate with an empty `string`/`string_view` test(CS(""), CS(""), CS("")); test(CS(""), CS("short"), CS("short")); test(CS(""), CS("not so short"), CS("not so short")); @@ -138,22 +137,16 @@ constexpr bool test() { test>(); test, min_allocator>(); test, safe_allocator>(); - // test, test_allocator>(); test>(); test, min_allocator>(); test, safe_allocator>(); - // test, test_allocator>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test>(); - // test, min_allocator>(); test, safe_allocator>(); - // test, test_allocator>(); test>(); - // test, min_allocator>(); test, safe_allocator>(); - // test, test_allocator>(); #endif return true; From 38f6e853deb3dbc6b9020de509f30cfeb981b12f Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 11 Apr 2024 21:06:16 +0300 Subject: [PATCH 04/22] 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 = 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 ::__ template 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 Date: Sat, 13 Apr 2024 07:12:20 +0300 Subject: [PATCH 05/22] 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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, type_identity_t> __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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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, safe_allocator>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test>(); + test, min_allocator>(); test, safe_allocator>(); test>(); + test, min_allocator>(); test, safe_allocator>(); #endif From 292cd8f7a485d8ccdf9635c50bba1c4a88fc7532 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sat, 13 Apr 2024 07:13:20 +0300 Subject: [PATCH 06/22] 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, min_allocator>(); test, safe_allocator>(); - test>(); - test, min_allocator>(); - test, safe_allocator>(); #ifndef TEST_HAS_NO_WIDE_CHARACTERS test>(); test, min_allocator>(); test, safe_allocator>(); - - test>(); - test, min_allocator>(); - test, safe_allocator>(); #endif return true; From 9a86ea1a9c1c0eefca8bec6223b14bec108ee445 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Mon, 15 Apr 2024 12:23:24 +0300 Subject: [PATCH 07/22] 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 +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, + type_identity_t> __rhs); + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, type_identity_t> __rhs); + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(type_identity_t> __lhs, + const basic_string<_CharT, _Traits, _Allocator>& __rhs); + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(type_identity_t> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs); +#endif + template 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> __lhs, + // const basic_string<_CharT2, _Traits2, _Allocator2>& __rhs); + + // template + // friend constexpr basic_string<_CharT2, _Traits2, _Allocator2> + // operator+(type_identity_t>, const basic_string<_CharT2, _Traits2, _Allocator2>&); + + + // friend constexpr basic_string operator+ <>(type_identity_t, 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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, type_identity_t> __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 @@ -4046,8 +4098,19 @@ template _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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 AllocT = std::allocator> +template > constexpr void test() { - // Concatinate with an empty `string`/`string_view` + // Concatenate with an empty `string`/`string_view` test(CS(""), CS(""), CS("")); test(CS(""), CS("short"), CS("short")); test(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 constexpr bool test() { - test>(); - test, min_allocator>(); - test, safe_allocator>(); + test>(); + test, min_allocator>(); + test, safe_allocator>(); -#ifndef TEST_HAS_NO_WIDE_CHARACTERS - test>(); - test, min_allocator>(); - test, safe_allocator>(); -#endif + test>(); + test, min_allocator>(); + test, safe_allocator>(); return true; } +// constexpr bool test() { +// test(); +// #ifndef TEST_HAS_NO_WIDE_CHARACTERS +// test(); +// #endif +// #ifndef TEST_HAS_NO_CHAR8_T +// test(); +// #endif +// test(); +// test(); + +// return true; +// } + int main(int, char**) { - test(); - static_assert(test()); + // test(); + // static_assert(test()); + + test(); + static_assert(test()); +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + test(); + static_assert(test()); +#endif +#ifndef TEST_HAS_NO_CHAR8_T + test(); + static_assert(test()); +#endif + test(); + static_assert(test()); + test(); + static_assert(test()); return 0; } From 695b4b61acaf072c75d573aeef3545276b04b99d Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Mon, 15 Apr 2024 12:28:33 +0300 Subject: [PATCH 08/22] 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> __rhs); -template -_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> -operator+(basic_string<_CharT, _Traits, _Allocator>&& __lhs, type_identity_t> __rhs); - template _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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> __lhs, - // const basic_string<_CharT2, _Traits2, _Allocator2>& __rhs); - - // template - // friend constexpr basic_string<_CharT2, _Traits2, _Allocator2> - // operator+(type_identity_t>, const basic_string<_CharT2, _Traits2, _Allocator2>&); - - - // friend constexpr basic_string operator+ <>(type_identity_t, 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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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>(); test, min_allocator>(); test, safe_allocator>(); + test, test_allocator>(); test>(); test, min_allocator>(); test, safe_allocator>(); + test, test_allocator>(); return true; } -// constexpr bool test() { -// test(); -// #ifndef TEST_HAS_NO_WIDE_CHARACTERS -// test(); -// #endif -// #ifndef TEST_HAS_NO_CHAR8_T -// test(); -// #endif -// test(); -// test(); - -// return true; -// } - int main(int, char**) { - // test(); - // static_assert(test()); - test(); static_assert(test()); #ifndef TEST_HAS_NO_WIDE_CHARACTERS From 6b77e5a8428bffcd124f5dffb157ca9732c809b9 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 16 Apr 2024 09:41:32 +0300 Subject: [PATCH 09/22] 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 _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 +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, + type_identity_t> __rhs); + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(type_identity_t> __lhs, + const basic_string<_CharT, _Traits, _Allocator>& __rhs); + +template +_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> +operator+(type_identity_t> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs); + +#endif + extern template _LIBCPP_EXPORTED_FROM_ABI string operator+ , allocator >(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 -_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> -operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, - type_identity_t> __rhs); - -template -_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> -operator+(type_identity_t> __lhs, - const basic_string<_CharT, _Traits, _Allocator>& __rhs); - -template -_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> -operator+(type_identity_t> __lhs, basic_string<_CharT, _Traits, _Allocator>&& __rhs); -#endif - template class basic_string { private: From 694e6fdbd767d53c8634a6aa9e3861b686e1a242 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Thu, 9 May 2024 20:01:17 +0300 Subject: [PATCH 10/22] 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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(type_identity_t> __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 Date: Fri, 10 May 2024 08:44:25 +0300 Subject: [PATCH 11/22] 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 sv{x}; + std::basic_string st_{x, allocator}; + std::basic_string_view sv{st_}; const std::basic_string st{y, allocator}; std::same_as> 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 sv{x}; + std::basic_string st_{x, allocator}; + std::basic_string_view sv{st_}; std::basic_string st{y, allocator}; std::same_as> decltype(auto) result = sv + std::move(st); @@ -152,18 +154,18 @@ constexpr bool test() { int main(int, char**) { test(); static_assert(test()); -#ifndef TEST_HAS_NO_WIDE_CHARACTERS + #ifndef TEST_HAS_NO_WIDE_CHARACTERS test(); - static_assert(test()); -#endif -#ifndef TEST_HAS_NO_CHAR8_T + static_assert(test()); + #endif + #ifndef TEST_HAS_NO_CHAR8_T test(); - static_assert(test()); -#endif + static_assert(test()); + #endif test(); - static_assert(test()); + static_assert(test()); test(); - static_assert(test()); + static_assert(test()); return 0; } From 20b9120dcb071cb2b46c191052965b379ca4b6f0 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 10 May 2024 08:45:50 +0300 Subject: [PATCH 12/22] 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 st_{x, allocator}; - std::basic_string_view sv{st_}; + std::basic_string_view sv{x}; const std::basic_string st{y, allocator}; std::same_as> decltype(auto) result = sv + st; From a8c28fbfc83af1bc7cb6cd4ceeb1e6b4906e1a05 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 10 May 2024 08:48:30 +0300 Subject: [PATCH 13/22] 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(); static_assert(test()); - #ifndef TEST_HAS_NO_WIDE_CHARACTERS +#ifndef TEST_HAS_NO_WIDE_CHARACTERS test(); - static_assert(test()); - #endif - #ifndef TEST_HAS_NO_CHAR8_T + static_assert(test()); +#endif +#ifndef TEST_HAS_NO_CHAR8_T test(); - static_assert(test()); - #endif + static_assert(test()); +#endif test(); - static_assert(test()); + static_assert(test()); test(); - static_assert(test()); + static_assert(test()); return 0; } From bdbaf38a56b9958238ab292362f5f8c2cc17d274 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Fri, 10 May 2024 09:39:42 +0300 Subject: [PATCH 14/22] 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> __lhs, const basic_string<_CharT, _Traits, _Allocator>& __rhs); -template -_LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> -operator+(type_identity_t> __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 Date: Fri, 10 May 2024 15:26:46 +0300 Subject: [PATCH 15/22] 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> 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> 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 Date: Thu, 16 May 2024 21:19:58 +0300 Subject: [PATCH 16/22] 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 st_{x, allocator}; std::basic_string_view sv{st_}; std::basic_string st{y, allocator}; From da99993e40ee4672f2b6bd7f3c1ee03693262742 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Wed, 10 Jul 2024 22:53:52 +0300 Subject: [PATCH 17/22] 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 _LIBCPP_HIDE_FROM_ABI constexpr basic_string<_CharT, _Traits, _Allocator> operator+(const basic_string<_CharT, _Traits, _Allocator>& __lhs, type_identity_t> __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 From a7bf9a03d2327000cd11f9e258de1af6ea98cbb7 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sun, 14 Jul 2024 15:34:50 +0300 Subject: [PATCH 18/22] 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 > +class ConstConvertibleStringView { +public: + constexpr explicit ConstConvertibleStringView(const CharT* cs) : cs_{cs} {} + + constexpr operator std::basic_string_view() = delete; + constexpr operator std::basic_string_view() const { return std::basic_string_view(cs_); } + +private: + const CharT* cs_; +}; + +static_assert(!std::constructible_from, ConstConvertibleStringView>); +static_assert(!std::convertible_to, std::basic_string_view>); + +static_assert(std::constructible_from, const ConstConvertibleStringView>); +static_assert(std::convertible_to, std::basic_string_view>); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(!std::constructible_from, ConstConvertibleStringView>); +static_assert(!std::convertible_to, std::basic_string_view>); + +static_assert(std::constructible_from, const ConstConvertibleStringView>); +static_assert(std::convertible_to, std::basic_string_view>); +#endif + +template > +class NonConstConvertibleStringView { +public: + constexpr explicit NonConstConvertibleStringView(const CharT* cs) : cs_{cs} {} + + constexpr operator std::basic_string_view() { return std::basic_string_view(cs_); } + constexpr operator std::basic_string_view() const = delete; + +private: + const CharT* cs_; +}; + +static_assert(std::constructible_from, NonConstConvertibleStringView>); +static_assert(std::convertible_to, std::basic_string_view>); + +static_assert(!std::constructible_from, const NonConstConvertibleStringView>); +static_assert(!std::convertible_to, std::basic_string_view>); + +#ifndef TEST_HAS_NO_WIDE_CHARACTERS +static_assert(std::constructible_from, NonConstConvertibleStringView>); +static_assert(std::convertible_to, std::basic_string_view>); + +static_assert(!std::constructible_from, const NonConstConvertibleStringView>); +static_assert(!std::convertible_to, std::basic_string_view>); +#endif + #define CS(S) MAKE_CSTRING(CharT, S) #define ST(S, a) std::basic_string(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a) #define SV(S) std::basic_string_view(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 st{x, allocator}; + NonConstConvertibleStringView sv{y}; + + std::same_as> decltype(auto) result = st + sv; + assert(result == expected); + assert(result.get_allocator() == allocator); + LIBCPP_ASSERT(is_string_asan_correct(st + sv)); + } } template > @@ -153,21 +216,91 @@ constexpr bool test() { return true; } +template +constexpr bool test_const_convertible() { + + // string& + const_convertible_to_string_view + { + std::basic_string st{x, allocator}; + ConstConvertibleStringView sv{y}; + + std::same_as> 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 st{x, allocator}; + ConstConvertibleStringView sv{y}; + + std::same_as> 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 st{x, allocator}; + ConstConvertibleStringView sv{y}; + + std::same_as> 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 sv{x}; + std::basic_string st{y, allocator}; + + std::same_as> 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 sv{x}; + const std::basic_string st{y, allocator}; + + std::same_as> 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 st_{x, allocator}; + ConstConvertibleStringView sv{x}; + std::basic_string st{y, allocator}; + + std::same_as> 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(); static_assert(test()); -#ifndef TEST_HAS_NO_WIDE_CHARACTERS - test(); - static_assert(test()); -#endif -#ifndef TEST_HAS_NO_CHAR8_T - test(); - static_assert(test()); -#endif - test(); - static_assert(test()); - test(); - static_assert(test()); +// #ifndef TEST_HAS_NO_WIDE_CHARACTERS +// test(); +// static_assert(test()); +// #endif +// #ifndef TEST_HAS_NO_CHAR8_T +// test(); +// static_assert(test()); +// #endif + // test(); + // static_assert(test()); +// test(); +// static_assert(test()); return 0; } From d214ef1055b366633ddb1945c9466d2603424d69 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sun, 14 Jul 2024 17:15:36 +0300 Subject: [PATCH 19/22] 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 > -class ConstConvertibleStringView { +template > +class ConvertibleToStringView { public: - constexpr explicit ConstConvertibleStringView(const CharT* cs) : cs_{cs} {} + constexpr explicit ConvertibleToStringView(const CharT* cs) : cs_{cs} {} + // template + // constexpr explicit ConvertibleToStringView(std::basic_string str) : cs_{str.c_str()} {} - constexpr operator std::basic_string_view() = delete; - constexpr operator std::basic_string_view() const { return std::basic_string_view(cs_); } + constexpr operator std::basic_string_view() { return std::basic_string_view(cs_); } + constexpr operator std::basic_string_view() const { + return std::basic_string_view(cs_); + } private: const CharT* cs_; }; -static_assert(!std::constructible_from, ConstConvertibleStringView>); -static_assert(!std::convertible_to, std::basic_string_view>); - -static_assert(std::constructible_from, const ConstConvertibleStringView>); -static_assert(std::convertible_to, std::basic_string_view>); - -#ifndef TEST_HAS_NO_WIDE_CHARACTERS -static_assert(!std::constructible_from, ConstConvertibleStringView>); -static_assert(!std::convertible_to, std::basic_string_view>); - -static_assert(std::constructible_from, const ConstConvertibleStringView>); -static_assert(std::convertible_to, std::basic_string_view>); -#endif +// static_assert(!std::constructible_from, ConvertibleToStringView>); +// static_assert(!std::convertible_to, std::basic_string_view>); -template > -class NonConstConvertibleStringView { -public: - constexpr explicit NonConstConvertibleStringView(const CharT* cs) : cs_{cs} {} +static_assert(std::constructible_from, const ConvertibleToStringView>); +static_assert(std::convertible_to, std::basic_string_view>); - constexpr operator std::basic_string_view() { return std::basic_string_view(cs_); } - constexpr operator std::basic_string_view() const = delete; +// #ifndef TEST_HAS_NO_WIDE_CHARACTERS +// static_assert(!std::constructible_from, ConvertibleToStringView>); +// static_assert(!std::convertible_to, std::basic_string_view>); -private: - const CharT* cs_; -}; +// static_assert(std::constructible_from, const ConvertibleToStringView>); +// static_assert(std::convertible_to, std::basic_string_view>); +// #endif -static_assert(std::constructible_from, NonConstConvertibleStringView>); -static_assert(std::convertible_to, std::basic_string_view>); +static_assert(std::constructible_from, ConvertibleToStringView>); +static_assert(std::convertible_to, std::basic_string_view>); -static_assert(!std::constructible_from, const NonConstConvertibleStringView>); -static_assert(!std::convertible_to, std::basic_string_view>); +// static_assert(!std::constructible_from, const ConvertibleToStringView>); +// static_assert(!std::convertible_to, std::basic_string_view>); -#ifndef TEST_HAS_NO_WIDE_CHARACTERS -static_assert(std::constructible_from, NonConstConvertibleStringView>); -static_assert(std::convertible_to, std::basic_string_view>); +// #ifndef TEST_HAS_NO_WIDE_CHARACTERS +// static_assert(std::constructible_from, ConvertibleToStringView>); +// static_assert(std::convertible_to, std::basic_string_view>); -static_assert(!std::constructible_from, const NonConstConvertibleStringView>); -static_assert(!std::convertible_to, std::basic_string_view>); -#endif +// static_assert(!std::constructible_from, const ConvertibleToStringView>); +// static_assert(!std::convertible_to, std::basic_string_view>); +// #endif #define CS(S) MAKE_CSTRING(CharT, S) -#define ST(S, a) std::basic_string(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a) -#define SV(S) std::basic_string_view(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S)) +// #define ST(S, a) std::basic_string(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S), a) +// #define SV(S) std::basic_string_view(MAKE_CSTRING(CharT, S), MKSTR_LEN(CharT, S)) -template +template