2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___FORMAT_FORMAT_ARG_H
11 #define _LIBCPP___FORMAT_FORMAT_ARG_H
13 #include <__cxx03/__assert>
14 #include <__cxx03/__concepts/arithmetic.h>
15 #include <__cxx03/__config>
16 #include <__cxx03/__format/concepts.h>
17 #include <__cxx03/__format/format_parse_context.h>
18 #include <__cxx03/__functional/invoke.h>
19 #include <__cxx03/__fwd/format.h>
20 #include <__cxx03/__memory/addressof.h>
21 #include <__cxx03/__type_traits/conditional.h>
22 #include <__cxx03/__type_traits/remove_const.h>
23 #include <__cxx03/__utility/forward.h>
24 #include <__cxx03/__utility/move.h>
25 #include <__cxx03/__utility/unreachable.h>
26 #include <__cxx03/__variant/monostate.h>
27 #include <__cxx03/cstdint>
28 #include <__cxx03/string_view>
30 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
31 # pragma GCC system_header
35 #include <__cxx03/__undef_macros>
37 _LIBCPP_BEGIN_NAMESPACE_STD
39 #if _LIBCPP_STD_VER >= 20
42 /// The type stored in @ref basic_format_arg.
44 /// @note The 128-bit types are unconditionally in the list to avoid the values
45 /// of the enums to depend on the availability of 128-bit integers.
47 /// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This
48 /// limits the maximum number of elements to 32.
49 /// When modifying update the test
50 /// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp
51 /// It could be packed in 4-bits but that means a new type directly becomes an
52 /// ABI break. The packed type is 64-bit so this reduces the maximum number of
53 /// packed elements from 16 to 12.
55 /// @note Some members of this enum are an extension. These extensions need
56 /// special behaviour in visit_format_arg. There they need to be wrapped in a
57 /// handle to satisfy the user observable behaviour. The internal function
58 /// __visit_format_arg doesn't do this wrapping. So in the format functions
59 /// this function is used to avoid unneeded overhead.
60 enum class __arg_t
: uint8_t {
73 __const_char_type_ptr
,
79 inline constexpr unsigned __packed_arg_t_bits
= 5;
80 inline constexpr uint8_t __packed_arg_t_mask
= 0x1f;
82 inline constexpr unsigned __packed_types_storage_bits
= 64;
83 inline constexpr unsigned __packed_types_max
= __packed_types_storage_bits
/ __packed_arg_t_bits
;
85 _LIBCPP_HIDE_FROM_ABI
constexpr bool __use_packed_format_arg_store(size_t __size
) {
86 return __size
<= __packed_types_max
;
89 _LIBCPP_HIDE_FROM_ABI
constexpr __arg_t
__get_packed_type(uint64_t __types
, size_t __id
) {
90 _LIBCPP_ASSERT_INTERNAL(__id
<= __packed_types_max
, "");
93 __types
>>= __id
* __packed_arg_t_bits
;
95 return static_cast<__format::__arg_t
>(__types
& __packed_arg_t_mask
);
98 } // namespace __format
100 // This function is not user observable, so it can directly use the non-standard
101 // types of the "variant". See __arg_t for more details.
102 template <class _Visitor
, class _Context
>
103 _LIBCPP_HIDE_FROM_ABI
decltype(auto) __visit_format_arg(_Visitor
&& __vis
, basic_format_arg
<_Context
> __arg
) {
104 switch (__arg
.__type_
) {
105 case __format::__arg_t::__none
:
106 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__monostate_
);
107 case __format::__arg_t::__boolean
:
108 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__boolean_
);
109 case __format::__arg_t::__char_type
:
110 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__char_type_
);
111 case __format::__arg_t::__int
:
112 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__int_
);
113 case __format::__arg_t::__long_long
:
114 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__long_long_
);
115 case __format::__arg_t::__i128
:
116 # ifndef _LIBCPP_HAS_NO_INT128
117 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__i128_
);
119 __libcpp_unreachable();
121 case __format::__arg_t::__unsigned
:
122 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__unsigned_
);
123 case __format::__arg_t::__unsigned_long_long
:
124 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__unsigned_long_long_
);
125 case __format::__arg_t::__u128
:
126 # ifndef _LIBCPP_HAS_NO_INT128
127 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__u128_
);
129 __libcpp_unreachable();
131 case __format::__arg_t::__float
:
132 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__float_
);
133 case __format::__arg_t::__double
:
134 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__double_
);
135 case __format::__arg_t::__long_double
:
136 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__long_double_
);
137 case __format::__arg_t::__const_char_type_ptr
:
138 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__const_char_type_ptr_
);
139 case __format::__arg_t::__string_view
:
140 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__string_view_
);
141 case __format::__arg_t::__ptr
:
142 return std::invoke(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__ptr_
);
143 case __format::__arg_t::__handle
:
145 std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__arg
.__value_
.__handle_
});
148 __libcpp_unreachable();
151 # if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
153 template <class _Rp
, class _Visitor
, class _Context
>
154 _LIBCPP_HIDE_FROM_ABI _Rp
__visit_format_arg(_Visitor
&& __vis
, basic_format_arg
<_Context
> __arg
) {
155 switch (__arg
.__type_
) {
156 case __format::__arg_t::__none
:
157 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__monostate_
);
158 case __format::__arg_t::__boolean
:
159 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__boolean_
);
160 case __format::__arg_t::__char_type
:
161 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__char_type_
);
162 case __format::__arg_t::__int
:
163 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__int_
);
164 case __format::__arg_t::__long_long
:
165 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__long_long_
);
166 case __format::__arg_t::__i128
:
167 # ifndef _LIBCPP_HAS_NO_INT128
168 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__i128_
);
170 __libcpp_unreachable();
172 case __format::__arg_t::__unsigned
:
173 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__unsigned_
);
174 case __format::__arg_t::__unsigned_long_long
:
175 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__unsigned_long_long_
);
176 case __format::__arg_t::__u128
:
177 # ifndef _LIBCPP_HAS_NO_INT128
178 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__u128_
);
180 __libcpp_unreachable();
182 case __format::__arg_t::__float
:
183 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__float_
);
184 case __format::__arg_t::__double
:
185 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__double_
);
186 case __format::__arg_t::__long_double
:
187 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__long_double_
);
188 case __format::__arg_t::__const_char_type_ptr
:
189 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__const_char_type_ptr_
);
190 case __format::__arg_t::__string_view
:
191 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__string_view_
);
192 case __format::__arg_t::__ptr
:
193 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
.__value_
.__ptr_
);
194 case __format::__arg_t::__handle
:
195 return std::invoke_r
<_Rp
>(
196 std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__arg
.__value_
.__handle_
});
199 __libcpp_unreachable();
202 # endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
204 /// Contains the values used in basic_format_arg.
206 /// This is a separate type so it's possible to store the values and types in
208 template <class _Context
>
209 class __basic_format_arg_value
{
210 using _CharT
= typename
_Context::char_type
;
213 /// Contains the implementation for basic_format_arg::handle.
216 _LIBCPP_HIDE_FROM_ABI
explicit __handle(_Tp
& __v
) noexcept
217 : __ptr_(std::addressof(__v
)),
218 __format_([](basic_format_parse_context
<_CharT
>& __parse_ctx
, _Context
& __ctx
, const void* __ptr
) {
219 using _Dp
= remove_const_t
<_Tp
>;
220 using _Qp
= conditional_t
<__formattable_with
<const _Dp
, _Context
>, const _Dp
, _Dp
>;
221 static_assert(__formattable_with
<_Qp
, _Context
>, "Mandated by [format.arg]/10");
223 typename
_Context::template formatter_type
<_Dp
> __f
;
224 __parse_ctx
.advance_to(__f
.parse(__parse_ctx
));
225 __ctx
.advance_to(__f
.format(*const_cast<_Qp
*>(static_cast<const _Dp
*>(__ptr
)), __ctx
));
229 void (*__format_
)(basic_format_parse_context
<_CharT
>&, _Context
&, const void*);
233 monostate __monostate_
;
237 unsigned __unsigned_
;
238 long long __long_long_
;
239 unsigned long long __unsigned_long_long_
;
240 # ifndef _LIBCPP_HAS_NO_INT128
246 long double __long_double_
;
247 const _CharT
* __const_char_type_ptr_
;
248 basic_string_view
<_CharT
> __string_view_
;
253 // These constructors contain the exact storage type used. If adjustments are
254 // required, these will be done in __create_format_arg.
256 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value() noexcept
: __monostate_() {}
257 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(bool __value
) noexcept
: __boolean_(__value
) {}
258 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(_CharT __value
) noexcept
: __char_type_(__value
) {}
259 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(int __value
) noexcept
: __int_(__value
) {}
260 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(unsigned __value
) noexcept
: __unsigned_(__value
) {}
261 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(long long __value
) noexcept
: __long_long_(__value
) {}
262 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(unsigned long long __value
) noexcept
263 : __unsigned_long_long_(__value
) {}
264 # ifndef _LIBCPP_HAS_NO_INT128
265 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(__int128_t __value
) noexcept
: __i128_(__value
) {}
266 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(__uint128_t __value
) noexcept
: __u128_(__value
) {}
268 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(float __value
) noexcept
: __float_(__value
) {}
269 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(double __value
) noexcept
: __double_(__value
) {}
270 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(long double __value
) noexcept
: __long_double_(__value
) {}
271 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(const _CharT
* __value
) noexcept
: __const_char_type_ptr_(__value
) {}
272 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(basic_string_view
<_CharT
> __value
) noexcept
273 : __string_view_(__value
) {}
274 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(const void* __value
) noexcept
: __ptr_(__value
) {}
275 _LIBCPP_HIDE_FROM_ABI
__basic_format_arg_value(__handle
&& __value
) noexcept
: __handle_(std::move(__value
)) {}
278 template <class _Context
>
279 class _LIBCPP_TEMPLATE_VIS basic_format_arg
{
281 class _LIBCPP_TEMPLATE_VIS handle
;
283 _LIBCPP_HIDE_FROM_ABI
basic_format_arg() noexcept
: __type_
{__format::__arg_t::__none
} {}
285 _LIBCPP_HIDE_FROM_ABI
explicit operator bool() const noexcept
{ return __type_
!= __format::__arg_t::__none
; }
287 # if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
289 // This function is user facing, so it must wrap the non-standard types of
290 // the "variant" in a handle to stay conforming. See __arg_t for more details.
291 template <class _Visitor
>
292 _LIBCPP_HIDE_FROM_ABI
decltype(auto) visit(this basic_format_arg __arg
, _Visitor
&& __vis
) {
293 switch (__arg
.__type_
) {
294 # ifndef _LIBCPP_HAS_NO_INT128
295 case __format::__arg_t::__i128
: {
296 typename __basic_format_arg_value
<_Context
>::__handle __h
{__arg
.__value_
.__i128_
};
297 return std::invoke(std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__h
});
300 case __format::__arg_t::__u128
: {
301 typename __basic_format_arg_value
<_Context
>::__handle __h
{__arg
.__value_
.__u128_
};
302 return std::invoke(std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__h
});
306 return std::__visit_format_arg(std::forward
<_Visitor
>(__vis
), __arg
);
310 // This function is user facing, so it must wrap the non-standard types of
311 // the "variant" in a handle to stay conforming. See __arg_t for more details.
312 template <class _Rp
, class _Visitor
>
313 _LIBCPP_HIDE_FROM_ABI _Rp
visit(this basic_format_arg __arg
, _Visitor
&& __vis
) {
314 switch (__arg
.__type_
) {
315 # ifndef _LIBCPP_HAS_NO_INT128
316 case __format::__arg_t::__i128
: {
317 typename __basic_format_arg_value
<_Context
>::__handle __h
{__arg
.__value_
.__i128_
};
318 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__h
});
321 case __format::__arg_t::__u128
: {
322 typename __basic_format_arg_value
<_Context
>::__handle __h
{__arg
.__value_
.__u128_
};
323 return std::invoke_r
<_Rp
>(std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__h
});
327 return std::__visit_format_arg
<_Rp
>(std::forward
<_Visitor
>(__vis
), __arg
);
331 # endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
334 using char_type
= typename
_Context::char_type
;
336 // TODO FMT Implement constrain [format.arg]/4
337 // Constraints: The template specialization
338 // typename Context::template formatter_type<T>
339 // meets the Formatter requirements ([formatter.requirements]). The extent
340 // to which an implementation determines that the specialization meets the
341 // Formatter requirements is unspecified, except that as a minimum the
343 // typename Context::template formatter_type<T>()
344 // .format(declval<const T&>(), declval<Context&>())
345 // shall be well-formed when treated as an unevaluated operand.
348 __basic_format_arg_value
<_Context
> __value_
;
349 __format::__arg_t __type_
;
351 _LIBCPP_HIDE_FROM_ABI
explicit basic_format_arg(__format::__arg_t __type
,
352 __basic_format_arg_value
<_Context
> __value
) noexcept
353 : __value_(__value
), __type_(__type
) {}
356 template <class _Context
>
357 class _LIBCPP_TEMPLATE_VIS basic_format_arg
<_Context
>::handle
{
359 _LIBCPP_HIDE_FROM_ABI
void format(basic_format_parse_context
<char_type
>& __parse_ctx
, _Context
& __ctx
) const {
360 __handle_
.__format_(__parse_ctx
, __ctx
, __handle_
.__ptr_
);
363 _LIBCPP_HIDE_FROM_ABI
explicit handle(typename __basic_format_arg_value
<_Context
>::__handle
& __handle
) noexcept
364 : __handle_(__handle
) {}
367 typename __basic_format_arg_value
<_Context
>::__handle
& __handle_
;
370 // This function is user facing, so it must wrap the non-standard types of
371 // the "variant" in a handle to stay conforming. See __arg_t for more details.
372 template <class _Visitor
, class _Context
>
373 # if _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
374 _LIBCPP_DEPRECATED_IN_CXX26
376 _LIBCPP_HIDE_FROM_ABI
decltype(auto)
377 visit_format_arg(_Visitor
&& __vis
, basic_format_arg
<_Context
> __arg
) {
378 switch (__arg
.__type_
) {
379 # ifndef _LIBCPP_HAS_NO_INT128
380 case __format::__arg_t::__i128
: {
381 typename __basic_format_arg_value
<_Context
>::__handle __h
{__arg
.__value_
.__i128_
};
382 return std::invoke(std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__h
});
385 case __format::__arg_t::__u128
: {
386 typename __basic_format_arg_value
<_Context
>::__handle __h
{__arg
.__value_
.__u128_
};
387 return std::invoke(std::forward
<_Visitor
>(__vis
), typename basic_format_arg
<_Context
>::handle
{__h
});
389 # endif // _LIBCPP_STD_VER >= 26 && defined(_LIBCPP_HAS_EXPLICIT_THIS_PARAMETER)
391 return std::__visit_format_arg(std::forward
<_Visitor
>(__vis
), __arg
);
395 #endif //_LIBCPP_STD_VER >= 20
397 _LIBCPP_END_NAMESPACE_STD
401 #endif // _LIBCPP___FORMAT_FORMAT_ARG_H