1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___FORMAT_CONCEPTS_H |
11 | #define _LIBCPP___FORMAT_CONCEPTS_H |
12 | |
13 | #include <__concepts/same_as.h> |
14 | #include <__concepts/semiregular.h> |
15 | #include <__config> |
16 | #include <__format/format_parse_context.h> |
17 | #include <__fwd/format.h> |
18 | #include <__fwd/tuple.h> |
19 | #include <__tuple/tuple_size.h> |
20 | #include <__type_traits/is_specialization.h> |
21 | #include <__type_traits/remove_const.h> |
22 | #include <__type_traits/remove_reference.h> |
23 | #include <__utility/pair.h> |
24 | |
25 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
26 | # pragma GCC system_header |
27 | #endif |
28 | |
29 | _LIBCPP_BEGIN_NAMESPACE_STD |
30 | |
31 | #if _LIBCPP_STD_VER >= 20 |
32 | |
33 | /// The character type specializations of \ref formatter. |
34 | template <class _CharT> |
35 | concept __fmt_char_type = |
36 | same_as<_CharT, char> |
37 | # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
38 | || same_as<_CharT, wchar_t> |
39 | # endif |
40 | ; |
41 | |
42 | // The output iterator isn't specified. A formatter should accept any |
43 | // output_iterator. This iterator is a minimal iterator to test the concept. |
44 | // (Note testing for (w)format_context would be a valid choice, but requires |
45 | // selecting the proper one depending on the type of _CharT.) |
46 | template <class _CharT> |
47 | using __fmt_iter_for = _CharT*; |
48 | |
49 | template <class _Tp, class _Context, class _Formatter = typename _Context::template formatter_type<remove_const_t<_Tp>>> |
50 | concept __formattable_with = |
51 | semiregular<_Formatter> && |
52 | requires(_Formatter& __f, |
53 | const _Formatter& __cf, |
54 | _Tp&& __t, |
55 | _Context __fc, |
56 | basic_format_parse_context<typename _Context::char_type> __pc) { |
57 | { __f.parse(__pc) } -> same_as<typename decltype(__pc)::iterator>; |
58 | { __cf.format(__t, __fc) } -> same_as<typename _Context::iterator>; |
59 | }; |
60 | |
61 | template <class _Tp, class _CharT> |
62 | concept __formattable = |
63 | __formattable_with<remove_reference_t<_Tp>, basic_format_context<__fmt_iter_for<_CharT>, _CharT>>; |
64 | |
65 | # if _LIBCPP_STD_VER >= 23 |
66 | template <class _Tp, class _CharT> |
67 | concept formattable = __formattable<_Tp, _CharT>; |
68 | |
69 | // [tuple.like] defines a tuple-like exposition only concept. This concept is |
70 | // not related to that. Therefore it uses a different name for the concept. |
71 | // |
72 | // TODO FMT Add a test to validate we fail when using that concept after P2165 |
73 | // has been implemented. |
74 | template <class _Tp> |
75 | concept __fmt_pair_like = |
76 | __is_specialization_v<_Tp, pair> || (__is_specialization_v<_Tp, tuple> && tuple_size_v<_Tp> == 2); |
77 | |
78 | # endif //_LIBCPP_STD_VER >= 23 |
79 | #endif //_LIBCPP_STD_VER >= 20 |
80 | |
81 | _LIBCPP_END_NAMESPACE_STD |
82 | |
83 | #endif // _LIBCPP___FORMAT_CONCEPTS_H |
84 | |