[libc++][format] Adds container adaptor formatters.
Implements parts of
- P2286R8 Formatting Ranges
Depends on D140653
Reviewed By: ldionne, #libc
Differential Revision: https://reviews.llvm.org/D141290
NOKEYCHECK=True
GitOrigin-RevId: 04d4f4b3d4e4fd608a3bc3fe387006435f04b61d
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 81d488f..2d20244 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -302,6 +302,7 @@
__filesystem/u8path.h
__format/buffer.h
__format/concepts.h
+ __format/container_adaptor.h
__format/enable_insertable.h
__format/escaped_output_table.h
__format/extended_grapheme_cluster_table.h
diff --git a/include/__format/container_adaptor.h b/include/__format/container_adaptor.h
new file mode 100644
index 0000000..62b6981
--- /dev/null
+++ b/include/__format/container_adaptor.h
@@ -0,0 +1,70 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H
+#define _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+#include <__availability>
+#include <__config>
+#include <__format/concepts.h>
+#include <__format/formatter.h>
+#include <__format/range_default_formatter.h>
+#include <queue>
+#include <stack>
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 20
+
+// [container.adaptors.format] only specifies the library should provide the
+// formatter specializations, not which header should provide them.
+// Since <format> includes a lot of headers, add these headers here instead of
+// adding more dependencies like, locale, optinal, string, tuple, etc. to the
+// adaptor headers. To use the format functions users already include <format>.
+
+template <class _Adaptor, class _CharT>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT __formatter_container_adaptor {
+private:
+ using __maybe_const_adaptor = __fmt_maybe_const<_Adaptor, _CharT>;
+ formatter<typename _Adaptor::container_type, _CharT> __underlying_;
+
+public:
+ template <class _ParseContext>
+ _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
+ return __underlying_.parse(__ctx);
+ }
+
+ template <class _FormatContext>
+ _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
+ format(__maybe_const_adaptor& __adaptor, _FormatContext& __ctx) const {
+ return __underlying_.format(__adaptor.__get_container(), __ctx);
+ }
+};
+
+template <class _CharT, class _Tp, formattable<_CharT> _Container>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<queue<_Tp, _Container>, _CharT>
+ : public __formatter_container_adaptor<queue<_Tp, _Container>, _CharT> {};
+
+template <class _CharT, class _Tp, class _Container, class _Compare>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<priority_queue<_Tp, _Container, _Compare>, _CharT>
+ : public __formatter_container_adaptor<priority_queue<_Tp, _Container, _Compare>, _CharT> {};
+
+template <class _CharT, class _Tp, formattable<_CharT> _Container>
+struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<stack<_Tp, _Container>, _CharT>
+ : public __formatter_container_adaptor<stack<_Tp, _Container>, _CharT> {};
+
+#endif //_LIBCPP_STD_VER > 20
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___FORMAT_CONTAINER_ADAPTOR_H
diff --git a/include/__format/range_default_formatter.h b/include/__format/range_default_formatter.h
index ee1dc52..652c021 100644
--- a/include/__format/range_default_formatter.h
+++ b/include/__format/range_default_formatter.h
@@ -146,8 +146,6 @@
__range_default_formatter() = delete; // TODO FMT Implement
};
-// Dispatcher to select the specialization based on the type of the range.
-
template <ranges::input_range _Rp, class _CharT>
requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>)
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter<_Rp, _CharT>
diff --git a/include/format b/include/format
index aaac95b..2c583c1 100644
--- a/include/format
+++ b/include/format
@@ -178,6 +178,7 @@
#include <__config>
#include <__format/buffer.h>
#include <__format/concepts.h>
+#include <__format/container_adaptor.h>
#include <__format/enable_insertable.h>
#include <__format/format_arg.h>
#include <__format/format_arg_store.h>
diff --git a/include/module.modulemap.in b/include/module.modulemap.in
index 81f503e..aa4da4d 100644
--- a/include/module.modulemap.in
+++ b/include/module.modulemap.in
@@ -839,6 +839,7 @@
module __format {
module buffer { private header "__format/buffer.h" }
module concepts { private header "__format/concepts.h" }
+ module container_adaptor { private header "__format/container_adaptor.h" }
module enable_insertable { private header "__format/enable_insertable.h" }
module escaped_output_table { private header "__format/escaped_output_table.h" }
module extended_grapheme_cluster_table { private header "__format/extended_grapheme_cluster_table.h" }
diff --git a/include/queue b/include/queue
index c58da5e..6c1b892 100644
--- a/include/queue
+++ b/include/queue
@@ -382,6 +382,8 @@
swap(c, __q.c);
}
+ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; }
+
template <class _T1, class _C1>
friend
_LIBCPP_INLINE_VISIBILITY
@@ -633,6 +635,8 @@
void swap(priority_queue& __q)
_NOEXCEPT_(__is_nothrow_swappable<container_type>::value &&
__is_nothrow_swappable<value_compare>::value);
+
+ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; }
};
#if _LIBCPP_STD_VER >= 17
diff --git a/include/stack b/include/stack
index 2abbcd0..d653d1b 100644
--- a/include/stack
+++ b/include/stack
@@ -255,6 +255,8 @@
swap(c, __s.c);
}
+ _LIBCPP_NODISCARD _LIBCPP_HIDE_FROM_ABI const _Container& __get_container() const { return c; }
+
template <class T1, class _C1>
friend
bool