Skip to content

Conversation

mordante
Copy link
Member

@mordante mordante commented Feb 22, 2025

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

Fixes: #105342

Implements:
- 3944. Formatters converting sequences of char to sequences of wchar_t

Fixes: llvm#105342
@mordante mordante requested a review from a team as a code owner February 22, 2025 13:40
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Feb 22, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 22, 2025

@llvm/pr-subscribers-libcxx

Author: Mark de Wever (mordante)

Changes

Implements:

    1. Formatters converting sequences of char to sequences of wchar_t

Fixes: #105342


Full diff: https://github.com/llvm/llvm-project/pull/128355.diff

4 Files Affected:

  • (modified) libcxx/docs/Status/Cxx2cIssues.csv (+1-1)
  • (modified) libcxx/include/__format/formatter.h (+7-5)
  • (modified) libcxx/include/__format/formatter_string.h (+13)
  • (modified) libcxx/test/std/utilities/format/format.formattable/concept.formattable.compile.pass.cpp (+16)
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 <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",""
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<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
 
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<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;
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<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>();
 }

@mordante mordante merged commit 26be07b into llvm:main Feb 26, 2025
85 of 89 checks passed
@mordante mordante deleted the review/LWG3944 branch February 26, 2025 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

LWG3944: Formatters converting sequences of char to sequences of wchar_t
3 participants