[libc++][format] Disables narrow string to wide string formatters. (#128355)

Implements LWG3944: Formatters converting sequences of char to sequences
of wchar_t

Fixes: #105342
This commit is contained in:
Mark de Wever 2025-02-26 17:54:18 +01:00 committed by GitHub
parent a841cf91b3
commit 26be07b851
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 6 deletions

View File

@ -62,7 +62,7 @@
"`LWG4053 <https://wg21.link/LWG4053>`__","Unary call to ``std::views::repeat`` does not decay the argument","2024-03 (Tokyo)","|Complete|","19",""
"`LWG4054 <https://wg21.link/LWG4054>`__","Repeating a ``repeat_view`` should repeat the view","2024-03 (Tokyo)","|Complete|","19",""
"","","","","",""
"`LWG3944 <https://wg21.link/LWG3944>`__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","","",""
"`LWG3944 <https://wg21.link/LWG3944>`__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","|Complete|","21",""
"`LWG4060 <https://wg21.link/LWG4060>`__","``submdspan`` preconditions do not forbid creating invalid pointer","2024-06 (St. Louis)","","",""
"`LWG4061 <https://wg21.link/LWG4061>`__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","2024-06 (St. Louis)","|Complete|","19",""
"`LWG4071 <https://wg21.link/LWG4071>`__","``reference_wrapper`` comparisons are not SFINAE-friendly","2024-06 (St. Louis)","|Complete|","19",""

1 Issue # Issue Name Meeting Status First released version Notes
62 `LWG4053 <https://wg21.link/LWG4053>`__ Unary call to ``std::views::repeat`` does not decay the argument 2024-03 (Tokyo) |Complete| 19
63 `LWG4054 <https://wg21.link/LWG4054>`__ Repeating a ``repeat_view`` should repeat the view 2024-03 (Tokyo) |Complete| 19
64
65 `LWG3944 <https://wg21.link/LWG3944>`__ Formatters converting sequences of ``char`` to sequences of ``wchar_t`` 2024-06 (St. Louis) |Complete| 21
66 `LWG4060 <https://wg21.link/LWG4060>`__ ``submdspan`` preconditions do not forbid creating invalid pointer 2024-06 (St. Louis)
67 `LWG4061 <https://wg21.link/LWG4061>`__ Should ``std::basic_format_context`` be default-constructible/copyable/movable? 2024-06 (St. Louis) |Complete| 19
68 `LWG4071 <https://wg21.link/LWG4071>`__ ``reference_wrapper`` comparisons are not SFINAE-friendly 2024-06 (St. Louis) |Complete| 19

View File

@ -21,6 +21,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
#if _LIBCPP_STD_VER >= 20
struct __disabled_formatter {
__disabled_formatter() = delete;
__disabled_formatter(const __disabled_formatter&) = delete;
__disabled_formatter& operator=(const __disabled_formatter&) = delete;
};
/// The default formatter template.
///
/// [format.formatter.spec]/5
@ -31,11 +37,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
/// - is_copy_assignable_v<F>, and
/// - is_move_assignable_v<F>.
template <class _Tp, class _CharT>
struct _LIBCPP_TEMPLATE_VIS formatter {
formatter() = delete;
formatter(const formatter&) = delete;
formatter& operator=(const formatter&) = delete;
};
struct _LIBCPP_TEMPLATE_VIS formatter : __disabled_formatter {};
# if _LIBCPP_STD_VER >= 23

View File

@ -125,6 +125,19 @@ struct _LIBCPP_TEMPLATE_VIS formatter<basic_string_view<_CharT, _Traits>, _CharT
}
};
# if _LIBCPP_HAS_WIDE_CHARACTERS
template <>
struct formatter<char*, wchar_t> : __disabled_formatter {};
template <>
struct formatter<const char*, wchar_t> : __disabled_formatter {};
template <size_t _Size>
struct formatter<char[_Size], wchar_t> : __disabled_formatter {};
template <class _Traits, class _Allocator>
struct formatter<basic_string<char, _Traits, _Allocator>, wchar_t> : __disabled_formatter {};
template <class _Traits>
struct formatter<basic_string_view<char, _Traits>, wchar_t> : __disabled_formatter {};
# endif // _LIBCPP_HAS_WIDE_CHARACTERS
# if _LIBCPP_STD_VER >= 23
template <>
inline constexpr bool enable_nonlocking_formatter_optimization<char*> = true;

View File

@ -292,6 +292,21 @@ void test_LWG3631() {
assert_is_not_formattable<std::pair<volatile int, volatile int>, CharT>();
}
void test_LWG3944() {
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
assert_is_not_formattable<char*, wchar_t>();
assert_is_not_formattable<const char*, wchar_t>();
assert_is_not_formattable<char[42], wchar_t>();
assert_is_not_formattable<std::string, wchar_t>();
assert_is_not_formattable<std::string_view, wchar_t>();
assert_is_formattable<std::vector<char>, wchar_t>();
assert_is_formattable<std::set<char>, wchar_t>();
assert_is_formattable<std::map<char, char>, wchar_t>();
assert_is_formattable<std::tuple<char>, wchar_t>();
#endif
}
class c {
void f();
void fc() const;
@ -417,6 +432,7 @@ void test() {
test_P1636<CharT>();
test_P2286<CharT>();
test_LWG3631<CharT>();
test_LWG3944();
test_abstract_class<CharT>();
test_disabled<CharT>();
}