[libcxx-commits] [libcxx] [libc++] Avoid including <format> code in <optional> (PR #179466)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Mon Feb 16 03:06:41 PST 2026


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/179466

>From 2bf46120706f8ae2faa08247cf361f88e0c73e5f Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 3 Feb 2026 14:57:58 +0100
Subject: [PATCH] [libc++] Avoid including <format> code in <optional>

---
 libcxx/include/__format/format_context.h      |  7 ++-----
 .../__format/range_default_formatter.h        |  1 +
 libcxx/include/__format/range_format.h        | 16 +-------------
 libcxx/include/__fwd/format.h                 | 21 +++++++++++++++++--
 libcxx/include/optional                       |  2 +-
 5 files changed, 24 insertions(+), 23 deletions(-)

diff --git a/libcxx/include/__format/format_context.h b/libcxx/include/__format/format_context.h
index 9732ea9bf7f85..18eb13691a950 100644
--- a/libcxx/include/__format/format_context.h
+++ b/libcxx/include/__format/format_context.h
@@ -40,10 +40,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 20
 
-template <class _OutIt, class _CharT>
-  requires output_iterator<_OutIt, const _CharT&>
-class basic_format_context;
-
 #  if _LIBCPP_HAS_LOCALIZATION
 /**
  * Helper to create a basic_format_context.
@@ -71,7 +67,6 @@ using wformat_context = basic_format_context< back_insert_iterator<__format::__o
 #  endif
 
 template <class _OutIt, class _CharT>
-  requires output_iterator<_OutIt, const _CharT&>
 class _LIBCPP_PREFERRED_NAME(format_context)
     _LIBCPP_IF_WIDE_CHARACTERS(_LIBCPP_PREFERRED_NAME(wformat_context)) basic_format_context {
 public:
@@ -80,6 +75,8 @@ class _LIBCPP_PREFERRED_NAME(format_context)
   template <class _Tp>
   using formatter_type = formatter<_Tp, _CharT>;
 
+  static_assert(output_iterator<_OutIt, const _CharT&>, "[format.context]/p3 requires OutIt to be an output_iterator");
+
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI basic_format_arg<basic_format_context> arg(size_t __id) const noexcept {
     return __args_.get(__id);
   }
diff --git a/libcxx/include/__format/range_default_formatter.h b/libcxx/include/__format/range_default_formatter.h
index 2d2190657b1af..23dfb54957b64 100644
--- a/libcxx/include/__format/range_default_formatter.h
+++ b/libcxx/include/__format/range_default_formatter.h
@@ -22,6 +22,7 @@
 #include <__format/formatter.h>
 #include <__format/range_format.h>
 #include <__format/range_formatter.h>
+#include <__fwd/format.h>
 #include <__iterator/back_insert_iterator.h>
 #include <__ranges/concepts.h>
 #include <__ranges/data.h>
diff --git a/libcxx/include/__format/range_format.h b/libcxx/include/__format/range_format.h
index fe43923f9d940..0e297022cccdd 100644
--- a/libcxx/include/__format/range_format.h
+++ b/libcxx/include/__format/range_format.h
@@ -17,6 +17,7 @@
 #include <__concepts/same_as.h>
 #include <__config>
 #include <__format/fmt_pair_like.h>
+#include <__fwd/format.h>
 #include <__ranges/concepts.h>
 #include <__type_traits/remove_cvref.h>
 
@@ -24,21 +25,6 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 23
 
-_LIBCPP_DIAGNOSTIC_PUSH
-_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow")
-_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow")
-// This shadows map, set, and string.
-enum class range_format { disabled, map, set, sequence, string, debug_string };
-_LIBCPP_DIAGNOSTIC_POP
-
-template <class _Rp>
-constexpr range_format format_kind = [] {
-  // [format.range.fmtkind]/1
-  // A program that instantiates the primary template of format_kind is ill-formed.
-  static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type");
-  return range_format::disabled;
-}();
-
 template <ranges::input_range _Rp>
   requires same_as<_Rp, remove_cvref_t<_Rp>>
 inline constexpr range_format format_kind<_Rp> = [] {
diff --git a/libcxx/include/__fwd/format.h b/libcxx/include/__fwd/format.h
index b7f4cecb65c1e..e9d15360f12e6 100644
--- a/libcxx/include/__fwd/format.h
+++ b/libcxx/include/__fwd/format.h
@@ -11,7 +11,6 @@
 #define _LIBCPP___FWD_FORMAT_H
 
 #include <__config>
-#include <__iterator/concepts.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -25,12 +24,30 @@ template <class _Context>
 class basic_format_arg;
 
 template <class _OutIt, class _CharT>
-  requires output_iterator<_OutIt, const _CharT&>
 class basic_format_context;
 
 template <class _Tp, class _CharT = char>
 struct formatter;
 
+#  if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_DIAGNOSTIC_PUSH
+_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow")
+_LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow")
+// This shadows map, set, and string.
+enum class range_format { disabled, map, set, sequence, string, debug_string };
+_LIBCPP_DIAGNOSTIC_POP
+
+template <class _Rp>
+constexpr range_format format_kind = [] {
+  // [format.range.fmtkind]/1
+  // A program that instantiates the primary template of format_kind is ill-formed.
+  static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type");
+  return range_format::disabled;
+}();
+
+#  endif // _LIBCPP_STD_VER >= 23
+
 #endif // _LIBCPP_STD_VER >= 20
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/optional b/libcxx/include/optional
index b851a858ed26a..9a8fb15c02dae 100644
--- a/libcxx/include/optional
+++ b/libcxx/include/optional
@@ -265,10 +265,10 @@ namespace std {
 #  include <__concepts/invocable.h>
 #  include <__config>
 #  include <__exception/exception.h>
-#  include <__format/range_format.h>
 #  include <__functional/hash.h>
 #  include <__functional/invoke.h>
 #  include <__functional/unary_function.h>
+#  include <__fwd/format.h>
 #  include <__fwd/functional.h>
 #  include <__iterator/bounded_iter.h>
 #  include <__iterator/capacity_aware_iterator.h>



More information about the libcxx-commits mailing list