diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv index 1ec23dfabd5ea..8a521e7d6686e 100644 --- a/libcxx/docs/Status/Cxx2cIssues.csv +++ b/libcxx/docs/Status/Cxx2cIssues.csv @@ -62,7 +62,7 @@ "`LWG4053 `__","Unary call to ``std::views::repeat`` does not decay the argument","2024-03 (Tokyo)","|Complete|","19","" "`LWG4054 `__","Repeating a ``repeat_view`` should repeat the view","2024-03 (Tokyo)","|Complete|","19","" "","","","","","" -"`LWG3944 `__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","","","" +"`LWG3944 `__","Formatters converting sequences of ``char`` to sequences of ``wchar_t``","2024-06 (St. Louis)","|Complete|","21","" "`LWG4060 `__","``submdspan`` preconditions do not forbid creating invalid pointer","2024-06 (St. Louis)","","","" "`LWG4061 `__","Should ``std::basic_format_context`` be default-constructible/copyable/movable?","2024-06 (St. Louis)","|Complete|","19","" "`LWG4071 `__","``reference_wrapper`` comparisons are not SFINAE-friendly","2024-06 (St. Louis)","|Complete|","19","" diff --git a/libcxx/include/__format/formatter.h b/libcxx/include/__format/formatter.h index 10c244b6d1895..e8386f5ca9c79 100644 --- a/libcxx/include/__format/formatter.h +++ b/libcxx/include/__format/formatter.h @@ -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, and /// - is_move_assignable_v. template -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 diff --git a/libcxx/include/__format/formatter_string.h b/libcxx/include/__format/formatter_string.h index 30084e582214d..112c731e67ed7 100644 --- a/libcxx/include/__format/formatter_string.h +++ b/libcxx/include/__format/formatter_string.h @@ -125,6 +125,19 @@ struct _LIBCPP_TEMPLATE_VIS formatter, _CharT } }; +# if _LIBCPP_HAS_WIDE_CHARACTERS +template <> +struct formatter : __disabled_formatter {}; +template <> +struct formatter : __disabled_formatter {}; +template +struct formatter : __disabled_formatter {}; +template +struct formatter, wchar_t> : __disabled_formatter {}; +template +struct formatter, wchar_t> : __disabled_formatter {}; +# endif // _LIBCPP_HAS_WIDE_CHARACTERS + # if _LIBCPP_STD_VER >= 23 template <> inline constexpr bool enable_nonlocking_formatter_optimization = true; diff --git a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp index ec27acd75e110..ac60307766d24 100644 --- a/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp +++ b/libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp @@ -292,6 +292,21 @@ void test_LWG3631() { assert_is_not_formattable, CharT>(); } +void test_LWG3944() { +#ifndef TEST_HAS_NO_WIDE_CHARACTERS + assert_is_not_formattable(); + assert_is_not_formattable(); + assert_is_not_formattable(); + assert_is_not_formattable(); + assert_is_not_formattable(); + + assert_is_formattable, wchar_t>(); + assert_is_formattable, wchar_t>(); + assert_is_formattable, wchar_t>(); + assert_is_formattable, wchar_t>(); +#endif +} + class c { void f(); void fc() const; @@ -417,6 +432,7 @@ void test() { test_P1636(); test_P2286(); test_LWG3631(); + test_LWG3944(); test_abstract_class(); test_disabled(); }