diff --git a/stl/inc/xstring b/stl/inc/xstring index 8aaf1dbfd8e..fcbf81f69a1 100644 --- a/stl/inc/xstring +++ b/stl/inc/xstring @@ -65,7 +65,8 @@ struct _Char_traits { // properties of a string or stream element return _First1; } - _Pre_satisfies_(_Dest_size >= _Count) static _Elem* _Copy_s(_Out_writes_all_(_Dest_size) _Elem* const _First1, + _Pre_satisfies_(_Dest_size >= _Count) static _CONSTEXPR20 _Elem* _Copy_s(_Out_writes_all_(_Dest_size) + _Elem* const _First1, const size_t _Dest_size, _In_reads_(_Count) const _Elem* const _First2, const size_t _Count) noexcept { // copy [_First2, _First2 + _Count) to [_First1, _First1 + _Dest_size) _STL_VERIFY(_Count <= _Dest_size, "invalid argument"); @@ -363,14 +364,7 @@ public: _In_reads_(_Count) const _Elem* const _First2, const size_t _Count) noexcept /* strengthened */ { // compare [_First1, _First1 + _Count) with [_First2, ...) #if _HAS_CXX17 -#if _HAS_U8_INTRINSICS - if constexpr (is_same_v<_Elem, char8_t>) { - return __builtin_u8memcmp(_First1, _First2, _Count); - } else -#endif // _HAS_U8_INTRINSICS - { - return __builtin_memcmp(_First1, _First2, _Count); - } + return __builtin_memcmp(_First1, _First2, _Count); #else // _HAS_CXX17 return _CSTD memcmp(_First1, _First2, _Count); #endif // _HAS_CXX17 @@ -1372,8 +1366,9 @@ public: return _Count; } - _Pre_satisfies_(_Dest_size >= _Count) constexpr size_type _Copy_s(_Out_writes_all_(_Dest_size) _Elem* const _Dest, - const size_type _Dest_size, size_type _Count, const size_type _Off = 0) const { + _Pre_satisfies_(_Dest_size >= _Count) _CONSTEXPR20 size_type + _Copy_s(_Out_writes_all_(_Dest_size) _Elem* const _Dest, const size_type _Dest_size, size_type _Count, + const size_type _Off = 0) const { // copy [_Off, _Off + _Count) to [_Dest, _Dest + _Count) _Check_offset(_Off); _Count = _Clamp_suffix_size(_Off, _Count); diff --git a/tests/std/tests/P0220R1_string_view/test.cpp b/tests/std/tests/P0220R1_string_view/test.cpp index 07d122bc42d..ef9d7027f35 100644 --- a/tests/std/tests/P0220R1_string_view/test.cpp +++ b/tests/std/tests/P0220R1_string_view/test.cpp @@ -1034,11 +1034,11 @@ static_assert(test_case_iterators()); static_assert(test_case_prefix()); static_assert(test_case_suffix()); static_assert(test_case_swap()); -static_assert(test_case_Copy_s()); static_assert(test_case_substr()); static_assert(test_case_compare()); #if _HAS_CXX20 static_assert(test_case_copy()); +static_assert(test_case_Copy_s()); static_assert(test_case_starts_with_ends_with()); #endif // _HAS_CXX20 static_assert(test_case_operators()); diff --git a/tests/std/tests/P1032R1_miscellaneous_constexpr/test.cpp b/tests/std/tests/P1032R1_miscellaneous_constexpr/test.cpp index 7ba268e9604..b66ebf80fc1 100644 --- a/tests/std/tests/P1032R1_miscellaneous_constexpr/test.cpp +++ b/tests/std/tests/P1032R1_miscellaneous_constexpr/test.cpp @@ -272,7 +272,7 @@ constexpr bool run_tests() { assert(last - first == static_cast(needle.size())); } - // test char_traits move/copy/assign and basic_string_view::copy + // test char_traits assign/copy/_Copy_s/move and basic_string_view::copy/_Copy_s { using Elem = char; using Traits = char_traits; @@ -314,6 +314,15 @@ constexpr bool run_tests() { assert(Traits::move(buf + 5, buf + 3, 11) == buf + 5); // overlapping, dest after src assert(buf == "....a.ababcbabc.c.."sv); + + assert(Traits::_Copy_s(buf, 20, src, 18) == buf); + assert(buf == "cute fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 4, 10) == 4); + assert(buf == "abc. fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 11) == 11); + assert(buf == "..........a KITTEN."sv); } { @@ -357,6 +366,15 @@ constexpr bool run_tests() { assert(Traits::move(buf + 5, buf + 3, 11) == buf + 5); // overlapping, dest after src assert(buf == u"....a.ababcbabc.c.."sv); + + assert(Traits::_Copy_s(buf, 20, src, 18) == buf); + assert(buf == u"cute fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 4, 10) == 4); + assert(buf == u"abc. fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 11) == 11); + assert(buf == u"..........a KITTEN."sv); } { @@ -400,6 +418,15 @@ constexpr bool run_tests() { assert(Traits::move(buf + 5, buf + 3, 11) == buf + 5); // overlapping, dest after src assert(buf == U"....a.ababcbabc.c.."sv); + + assert(Traits::_Copy_s(buf, 20, src, 18) == buf); + assert(buf == U"cute fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 4, 10) == 4); + assert(buf == U"abc. fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 11) == 11); + assert(buf == U"..........a KITTEN."sv); } { @@ -443,6 +470,15 @@ constexpr bool run_tests() { assert(Traits::move(buf + 5, buf + 3, 11) == buf + 5); // overlapping, dest after src assert(buf == L"....a.ababcbabc.c.."sv); + + assert(Traits::_Copy_s(buf, 20, src, 18) == buf); + assert(buf == L"cute fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 4, 10) == 4); + assert(buf == L"abc. fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 11) == 11); + assert(buf == L"..........a KITTEN."sv); } #ifdef __cpp_lib_char8_t @@ -487,9 +523,51 @@ constexpr bool run_tests() { assert(Traits::move(buf + 5, buf + 3, 11) == buf + 5); // overlapping, dest after src assert(buf == u8"....a.ababcbabc.c.."sv); + + assert(Traits::_Copy_s(buf, 20, src, 18) == buf); + assert(buf == u8"cute fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 4, 10) == 4); + assert(buf == u8"abc. fluffy KITTEN."sv); + + assert(sv._Copy_s(buf, 20, 11) == 11); + assert(buf == u8"..........a KITTEN."sv); } #endif // __cpp_lib_char8_t + // test char_traits::compare refactoring through basic_string_view (not part of P1032R1) + { + assert("cat"sv == "cat"sv); + assert("cat"sv < "category"sv); + assert("catastrophe"sv > "cat"sv); + assert("catch"sv < "category"sv); + assert("catenary"sv > "catapult"sv); + + assert(u"cat"sv == u"cat"sv); + assert(u"cat"sv < u"category"sv); + assert(u"catastrophe"sv > u"cat"sv); + assert(u"catch"sv < u"category"sv); + assert(u"catenary"sv > u"catapult"sv); + + assert(U"cat"sv == U"cat"sv); + assert(U"cat"sv < U"category"sv); + assert(U"catastrophe"sv > U"cat"sv); + assert(U"catch"sv < U"category"sv); + assert(U"catenary"sv > U"catapult"sv); + + assert(L"cat"sv == L"cat"sv); + assert(L"cat"sv < L"category"sv); + assert(L"catastrophe"sv > L"cat"sv); + assert(L"catch"sv < L"category"sv); + assert(L"catenary"sv > L"catapult"sv); + + assert(u8"cat"sv == u8"cat"sv); + assert(u8"cat"sv < u8"category"sv); + assert(u8"catastrophe"sv > u8"cat"sv); + assert(u8"catch"sv < u8"category"sv); + assert(u8"catenary"sv > u8"catapult"sv); + } + return true; }