[libc++][format] Adds a formattable concept.
The concept is based on P2286R2 Formatting Ranges. It will be used to
optimise the storage of __format_arg_store as required by LWG-3473.
Depends on D120916
Reviewed By: #libc, Mordante
Differential Revision: https://reviews.llvm.org/D120921
NOKEYCHECK=True
GitOrigin-RevId: 15c809e8e78083d59f1c0b09ca1d1644e0976961
diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
index 55ac4db..2da8b98 100644
--- a/include/CMakeLists.txt
+++ b/include/CMakeLists.txt
@@ -209,6 +209,7 @@
__filesystem/space_info.h
__filesystem/u8path.h
__format/buffer.h
+ __format/concepts.h
__format/enable_insertable.h
__format/format_arg.h
__format/format_args.h
diff --git a/include/__format/concepts.h b/include/__format/concepts.h
new file mode 100644
index 0000000..8df6493
--- /dev/null
+++ b/include/__format/concepts.h
@@ -0,0 +1,53 @@
+// -*- 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_CONCEPTS_H
+#define _LIBCPP___FORMAT_CONCEPTS_H
+
+#include <__concepts/same_as.h>
+#include <__concepts/semiregular.h>
+#include <__config>
+#include <__format/format_fwd.h>
+#include <__format/format_parse_context.h>
+#include <type_traits>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+# pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+#if _LIBCPP_STD_VER > 17
+
+// The output iterator isn't specified. A formatter should accept any
+// output_iterator. This iterator is a minimal iterator to test the concept.
+// (Note testing for (w)format_context would be a valid choice, but requires
+// selecting the proper one depending on the type of _CharT.)
+template <class _CharT>
+using __fmt_iter_for = _CharT*;
+
+// The concept is based on P2286R6
+// It lacks the const of __cf as required by, the not yet accepted, LWG-3636.
+// The current formatters can't be easily adapted, but that is WIP.
+// TODO FMT properly implement this concepts once accepted.
+template <class _Tp, class _CharT>
+concept __formattable = (semiregular<formatter<remove_cvref_t<_Tp>, _CharT>>) &&
+ requires(formatter<remove_cvref_t<_Tp>, _CharT> __f,
+ formatter<remove_cvref_t<_Tp>, _CharT> __cf, _Tp __t,
+ basic_format_context<__fmt_iter_for<_CharT>, _CharT> __fc,
+ basic_format_parse_context<_CharT> __pc) {
+ { __f.parse(__pc) } -> same_as<typename basic_format_parse_context<_CharT>::iterator>;
+ { __cf.format(__t, __fc) } -> same_as<__fmt_iter_for<_CharT>>;
+ };
+
+#endif //_LIBCPP_STD_VER > 17
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP___FORMAT_CONCEPTS_H
diff --git a/include/__format/format_fwd.h b/include/__format/format_fwd.h
index 0f2e908..908d10d 100644
--- a/include/__format/format_fwd.h
+++ b/include/__format/format_fwd.h
@@ -12,6 +12,7 @@
#include <__availability>
#include <__config>
+#include <__iterator/concepts.h>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -27,6 +28,10 @@
template <class _Context, class... _Args>
struct _LIBCPP_TEMPLATE_VIS __format_arg_store;
+template <class _OutIt, class _CharT>
+ requires output_iterator<_OutIt, const _CharT&>
+class _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT basic_format_context;
+
template <class _Tp, class _CharT = char>
struct _LIBCPP_TEMPLATE_VIS _LIBCPP_AVAILABILITY_FORMAT formatter;
diff --git a/include/format b/include/format
index 9516278..070bfe2 100644
--- a/include/format
+++ b/include/format
@@ -127,6 +127,7 @@
#include <__config>
#include <__debug>
#include <__format/buffer.h>
+#include <__format/concepts.h>
#include <__format/enable_insertable.h>
#include <__format/format_arg.h>
#include <__format/format_args.h>
diff --git a/include/module.modulemap b/include/module.modulemap
index 7ae3d10..ef97b81 100644
--- a/include/module.modulemap
+++ b/include/module.modulemap
@@ -542,6 +542,7 @@
module __format {
module buffer { private header "__format/buffer.h" }
+ module concepts { private header "__format/concepts.h" }
module enable_insertable { private header "__format/enable_insertable.h" }
module format_arg { private header "__format/format_arg.h" }
module format_args { private header "__format/format_args.h" }