10922ce56SMark de Wever // -*- C++ -*- 20922ce56SMark de Wever //===----------------------------------------------------------------------===// 30922ce56SMark de Wever // 40922ce56SMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 50922ce56SMark de Wever // See https://llvm.org/LICENSE.txt for license information. 60922ce56SMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 70922ce56SMark de Wever // 80922ce56SMark de Wever //===----------------------------------------------------------------------===// 90922ce56SMark de Wever 100922ce56SMark de Wever #ifndef _LIBCPP___FORMAT_FORMAT_ARG_H 110922ce56SMark de Wever #define _LIBCPP___FORMAT_FORMAT_ARG_H 120922ce56SMark de Wever 13f87aa19bSLouis Dionne #include <__assert> 1416379211SMark de Wever #include <__concepts/arithmetic.h> 150922ce56SMark de Wever #include <__config> 16e99c4906SNikolas Klauser #include <__cstddef/size_t.h> 1748abcf11SMark de Wever #include <__format/concepts.h> 18ade6d0d8SMark de Wever #include <__format/format_parse_context.h> 1934f73804SNikolas Klauser #include <__functional/invoke.h> 2008766681SNikolas Klauser #include <__fwd/format.h> 21ade6d0d8SMark de Wever #include <__memory/addressof.h> 2279702f7fSIan Anderson #include <__type_traits/conditional.h> 23472b612cSNikolas Klauser #include <__type_traits/remove_const.h> 2434f73804SNikolas Klauser #include <__utility/forward.h> 25285e1e2aSMark de Wever #include <__utility/move.h> 262a8f9a5eSNikolas Klauser #include <__utility/unreachable.h> 270922ce56SMark de Wever #include <__variant/monostate.h> 28285e1e2aSMark de Wever #include <cstdint> 290922ce56SMark de Wever #include <string_view> 300922ce56SMark de Wever 310922ce56SMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 320922ce56SMark de Wever # pragma GCC system_header 330922ce56SMark de Wever #endif 340922ce56SMark de Wever 357b462251SLouis Dionne _LIBCPP_PUSH_MACROS 367b462251SLouis Dionne #include <__undef_macros> 377b462251SLouis Dionne 380922ce56SMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD 390922ce56SMark de Wever 404f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 20 410922ce56SMark de Wever 420922ce56SMark de Wever namespace __format { 43dfb20d4dSMark de Wever /// The type stored in @ref basic_format_arg. 44dfb20d4dSMark de Wever /// 45dfb20d4dSMark de Wever /// @note The 128-bit types are unconditionally in the list to avoid the values 46dfb20d4dSMark de Wever /// of the enums to depend on the availability of 128-bit integers. 474d8268fbSMark de Wever /// 484d8268fbSMark de Wever /// @note The value is stored as a 5-bit value in the __packed_arg_t_bits. This 494d8268fbSMark de Wever /// limits the maximum number of elements to 32. 504d8268fbSMark de Wever /// When modifying update the test 514d8268fbSMark de Wever /// test/libcxx/utilities/format/format.arguments/format.arg/arg_t.compile.pass.cpp 524d8268fbSMark de Wever /// It could be packed in 4-bits but that means a new type directly becomes an 534d8268fbSMark de Wever /// ABI break. The packed type is 64-bit so this reduces the maximum number of 544d8268fbSMark de Wever /// packed elements from 16 to 12. 55e948cab0SMark de Wever /// 56e948cab0SMark de Wever /// @note Some members of this enum are an extension. These extensions need 57e948cab0SMark de Wever /// special behaviour in visit_format_arg. There they need to be wrapped in a 58e948cab0SMark de Wever /// handle to satisfy the user observable behaviour. The internal function 59e948cab0SMark de Wever /// __visit_format_arg doesn't do this wrapping. So in the format functions 60e948cab0SMark de Wever /// this function is used to avoid unneeded overhead. 613583bf3aSNikolas Klauser enum class __arg_t : uint8_t { 620922ce56SMark de Wever __none, 6367794e78SMark de Wever __boolean, 640922ce56SMark de Wever __char_type, 650922ce56SMark de Wever __int, 660922ce56SMark de Wever __long_long, 67e948cab0SMark de Wever __i128, // extension 680922ce56SMark de Wever __unsigned, 690922ce56SMark de Wever __unsigned_long_long, 70e948cab0SMark de Wever __u128, // extension 710922ce56SMark de Wever __float, 720922ce56SMark de Wever __double, 730922ce56SMark de Wever __long_double, 740922ce56SMark de Wever __const_char_type_ptr, 750922ce56SMark de Wever __string_view, 76ade6d0d8SMark de Wever __ptr, 77ade6d0d8SMark de Wever __handle 780922ce56SMark de Wever }; 794d8268fbSMark de Wever 804d8268fbSMark de Wever inline constexpr unsigned __packed_arg_t_bits = 5; 814d8268fbSMark de Wever inline constexpr uint8_t __packed_arg_t_mask = 0x1f; 824d8268fbSMark de Wever 834d8268fbSMark de Wever inline constexpr unsigned __packed_types_storage_bits = 64; 844d8268fbSMark de Wever inline constexpr unsigned __packed_types_max = __packed_types_storage_bits / __packed_arg_t_bits; 854d8268fbSMark de Wever 869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr bool __use_packed_format_arg_store(size_t __size) { 879783f28cSLouis Dionne return __size <= __packed_types_max; 889783f28cSLouis Dionne } 894d8268fbSMark de Wever 909783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { 914f215fddSKonstantin Varlamov _LIBCPP_ASSERT_INTERNAL(__id <= __packed_types_max, ""); 924d8268fbSMark de Wever 934d8268fbSMark de Wever if (__id > 0) 944d8268fbSMark de Wever __types >>= __id * __packed_arg_t_bits; 954d8268fbSMark de Wever 964d8268fbSMark de Wever return static_cast<__format::__arg_t>(__types & __packed_arg_t_mask); 974d8268fbSMark de Wever } 984d8268fbSMark de Wever 990922ce56SMark de Wever } // namespace __format 1000922ce56SMark de Wever 10127e67cdbSHristo Hristov // This function is not user observable, so it can directly use the non-standard 102e948cab0SMark de Wever // types of the "variant". See __arg_t for more details. 1030922ce56SMark de Wever template <class _Visitor, class _Context> 1049783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI decltype(auto) __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 1050922ce56SMark de Wever switch (__arg.__type_) { 1060922ce56SMark de Wever case __format::__arg_t::__none: 10777a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_); 10867794e78SMark de Wever case __format::__arg_t::__boolean: 10977a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_); 1100922ce56SMark de Wever case __format::__arg_t::__char_type: 11177a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_); 1120922ce56SMark de Wever case __format::__arg_t::__int: 11377a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__int_); 1140922ce56SMark de Wever case __format::__arg_t::__long_long: 11577a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_); 1160922ce56SMark de Wever case __format::__arg_t::__i128: 117ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 11877a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__i128_); 119dfb20d4dSMark de Wever # else 1202a8f9a5eSNikolas Klauser __libcpp_unreachable(); 1210922ce56SMark de Wever # endif 1220922ce56SMark de Wever case __format::__arg_t::__unsigned: 12377a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_); 1240922ce56SMark de Wever case __format::__arg_t::__unsigned_long_long: 12577a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); 1260922ce56SMark de Wever case __format::__arg_t::__u128: 127ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 12877a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__u128_); 129dfb20d4dSMark de Wever # else 1302a8f9a5eSNikolas Klauser __libcpp_unreachable(); 1310922ce56SMark de Wever # endif 1320922ce56SMark de Wever case __format::__arg_t::__float: 13377a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__float_); 1340922ce56SMark de Wever case __format::__arg_t::__double: 13577a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__double_); 1360922ce56SMark de Wever case __format::__arg_t::__long_double: 13777a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_); 1380922ce56SMark de Wever case __format::__arg_t::__const_char_type_ptr: 13977a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_); 1400922ce56SMark de Wever case __format::__arg_t::__string_view: 14177a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_); 1420922ce56SMark de Wever case __format::__arg_t::__ptr: 14377a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_); 144ade6d0d8SMark de Wever case __format::__arg_t::__handle: 1459783f28cSLouis Dionne return std::invoke( 1469783f28cSLouis Dionne std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_}); 1470922ce56SMark de Wever } 1484d8268fbSMark de Wever 1492a8f9a5eSNikolas Klauser __libcpp_unreachable(); 1500922ce56SMark de Wever } 1510922ce56SMark de Wever 152ba87515fSNikolas Klauser # if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 15327e67cdbSHristo Hristov 15427e67cdbSHristo Hristov template <class _Rp, class _Visitor, class _Context> 15527e67cdbSHristo Hristov _LIBCPP_HIDE_FROM_ABI _Rp __visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 15627e67cdbSHristo Hristov switch (__arg.__type_) { 15727e67cdbSHristo Hristov case __format::__arg_t::__none: 15827e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__monostate_); 15927e67cdbSHristo Hristov case __format::__arg_t::__boolean: 16027e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__boolean_); 16127e67cdbSHristo Hristov case __format::__arg_t::__char_type: 16227e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__char_type_); 16327e67cdbSHristo Hristov case __format::__arg_t::__int: 16427e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__int_); 16527e67cdbSHristo Hristov case __format::__arg_t::__long_long: 16627e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_long_); 16727e67cdbSHristo Hristov case __format::__arg_t::__i128: 168ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 16927e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__i128_); 17027e67cdbSHristo Hristov # else 17127e67cdbSHristo Hristov __libcpp_unreachable(); 17227e67cdbSHristo Hristov # endif 17327e67cdbSHristo Hristov case __format::__arg_t::__unsigned: 17427e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_); 17527e67cdbSHristo Hristov case __format::__arg_t::__unsigned_long_long: 17627e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__unsigned_long_long_); 17727e67cdbSHristo Hristov case __format::__arg_t::__u128: 178ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 17927e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__u128_); 18027e67cdbSHristo Hristov # else 18127e67cdbSHristo Hristov __libcpp_unreachable(); 18227e67cdbSHristo Hristov # endif 18327e67cdbSHristo Hristov case __format::__arg_t::__float: 18427e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__float_); 18527e67cdbSHristo Hristov case __format::__arg_t::__double: 18627e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__double_); 18727e67cdbSHristo Hristov case __format::__arg_t::__long_double: 18827e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__long_double_); 18927e67cdbSHristo Hristov case __format::__arg_t::__const_char_type_ptr: 19027e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__const_char_type_ptr_); 19127e67cdbSHristo Hristov case __format::__arg_t::__string_view: 19227e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__string_view_); 19327e67cdbSHristo Hristov case __format::__arg_t::__ptr: 19427e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), __arg.__value_.__ptr_); 19527e67cdbSHristo Hristov case __format::__arg_t::__handle: 19627e67cdbSHristo Hristov return std::invoke_r<_Rp>( 19727e67cdbSHristo Hristov std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__arg.__value_.__handle_}); 19827e67cdbSHristo Hristov } 19927e67cdbSHristo Hristov 20027e67cdbSHristo Hristov __libcpp_unreachable(); 20127e67cdbSHristo Hristov } 20227e67cdbSHristo Hristov 203ba87515fSNikolas Klauser # endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 20427e67cdbSHristo Hristov 2054d8268fbSMark de Wever /// Contains the values used in basic_format_arg. 2064d8268fbSMark de Wever /// 2074d8268fbSMark de Wever /// This is a separate type so it's possible to store the values and types in 2084d8268fbSMark de Wever /// separate arrays. 2094d8268fbSMark de Wever template <class _Context> 2104d8268fbSMark de Wever class __basic_format_arg_value { 211f6958523SNikolas Klauser using _CharT _LIBCPP_NODEBUG = typename _Context::char_type; 2124d8268fbSMark de Wever 2134d8268fbSMark de Wever public: 2144d8268fbSMark de Wever /// Contains the implementation for basic_format_arg::handle. 2154d8268fbSMark de Wever struct __handle { 2164d8268fbSMark de Wever template <class _Tp> 21748abcf11SMark de Wever _LIBCPP_HIDE_FROM_ABI explicit __handle(_Tp& __v) noexcept 21877a00c0dSLouis Dionne : __ptr_(std::addressof(__v)), 2194d8268fbSMark de Wever __format_([](basic_format_parse_context<_CharT>& __parse_ctx, _Context& __ctx, const void* __ptr) { 22048abcf11SMark de Wever using _Dp = remove_const_t<_Tp>; 22148abcf11SMark de Wever using _Qp = conditional_t<__formattable_with<const _Dp, _Context>, const _Dp, _Dp>; 22248abcf11SMark de Wever static_assert(__formattable_with<_Qp, _Context>, "Mandated by [format.arg]/10"); 223606e2808SMark de Wever 22448abcf11SMark de Wever typename _Context::template formatter_type<_Dp> __f; 2254d8268fbSMark de Wever __parse_ctx.advance_to(__f.parse(__parse_ctx)); 226606e2808SMark de Wever __ctx.advance_to(__f.format(*const_cast<_Qp*>(static_cast<const _Dp*>(__ptr)), __ctx)); 2274d8268fbSMark de Wever }) {} 2284d8268fbSMark de Wever 2294d8268fbSMark de Wever const void* __ptr_; 2304d8268fbSMark de Wever void (*__format_)(basic_format_parse_context<_CharT>&, _Context&, const void*); 2314d8268fbSMark de Wever }; 2324d8268fbSMark de Wever 2334d8268fbSMark de Wever union { 2344d8268fbSMark de Wever monostate __monostate_; 2354d8268fbSMark de Wever bool __boolean_; 2364d8268fbSMark de Wever _CharT __char_type_; 2374d8268fbSMark de Wever int __int_; 2384d8268fbSMark de Wever unsigned __unsigned_; 2394d8268fbSMark de Wever long long __long_long_; 2404d8268fbSMark de Wever unsigned long long __unsigned_long_long_; 241ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 2424d8268fbSMark de Wever __int128_t __i128_; 2434d8268fbSMark de Wever __uint128_t __u128_; 2444d8268fbSMark de Wever # endif 2454d8268fbSMark de Wever float __float_; 2464d8268fbSMark de Wever double __double_; 2474d8268fbSMark de Wever long double __long_double_; 2484d8268fbSMark de Wever const _CharT* __const_char_type_ptr_; 2494d8268fbSMark de Wever basic_string_view<_CharT> __string_view_; 2504d8268fbSMark de Wever const void* __ptr_; 2514d8268fbSMark de Wever __handle __handle_; 2524d8268fbSMark de Wever }; 2534d8268fbSMark de Wever 2544d8268fbSMark de Wever // These constructors contain the exact storage type used. If adjustments are 2554d8268fbSMark de Wever // required, these will be done in __create_format_arg. 2564d8268fbSMark de Wever 2574d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value() noexcept : __monostate_() {} 2584d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(bool __value) noexcept : __boolean_(__value) {} 2594d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(_CharT __value) noexcept : __char_type_(__value) {} 2604d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(int __value) noexcept : __int_(__value) {} 2614d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned __value) noexcept : __unsigned_(__value) {} 2624d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long long __value) noexcept : __long_long_(__value) {} 2634d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(unsigned long long __value) noexcept 2644d8268fbSMark de Wever : __unsigned_long_long_(__value) {} 265ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 2664d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__int128_t __value) noexcept : __i128_(__value) {} 2674d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__uint128_t __value) noexcept : __u128_(__value) {} 2684d8268fbSMark de Wever # endif 2694d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(float __value) noexcept : __float_(__value) {} 2704d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(double __value) noexcept : __double_(__value) {} 2714d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(long double __value) noexcept : __long_double_(__value) {} 2724d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const _CharT* __value) noexcept : __const_char_type_ptr_(__value) {} 2734d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(basic_string_view<_CharT> __value) noexcept 2744d8268fbSMark de Wever : __string_view_(__value) {} 2754d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(const void* __value) noexcept : __ptr_(__value) {} 27648abcf11SMark de Wever _LIBCPP_HIDE_FROM_ABI __basic_format_arg_value(__handle&& __value) noexcept : __handle_(std::move(__value)) {} 2774d8268fbSMark de Wever }; 2784d8268fbSMark de Wever 2790922ce56SMark de Wever template <class _Context> 280*6f684816SNikolas Klauser class _LIBCPP_TEMPLATE_VIS _LIBCPP_NO_SPECIALIZATIONS basic_format_arg { 2810922ce56SMark de Wever public: 282ade6d0d8SMark de Wever class _LIBCPP_TEMPLATE_VIS handle; 2830922ce56SMark de Wever 2849783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept : __type_{__format::__arg_t::__none} {} 2850922ce56SMark de Wever 2869783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI explicit operator bool() const noexcept { return __type_ != __format::__arg_t::__none; } 2870922ce56SMark de Wever 288ba87515fSNikolas Klauser # if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 28927e67cdbSHristo Hristov 29027e67cdbSHristo Hristov // This function is user facing, so it must wrap the non-standard types of 29127e67cdbSHristo Hristov // the "variant" in a handle to stay conforming. See __arg_t for more details. 29227e67cdbSHristo Hristov template <class _Visitor> 29327e67cdbSHristo Hristov _LIBCPP_HIDE_FROM_ABI decltype(auto) visit(this basic_format_arg __arg, _Visitor&& __vis) { 29427e67cdbSHristo Hristov switch (__arg.__type_) { 295ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 29627e67cdbSHristo Hristov case __format::__arg_t::__i128: { 29727e67cdbSHristo Hristov typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; 29827e67cdbSHristo Hristov return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 29927e67cdbSHristo Hristov } 30027e67cdbSHristo Hristov 30127e67cdbSHristo Hristov case __format::__arg_t::__u128: { 30227e67cdbSHristo Hristov typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; 30327e67cdbSHristo Hristov return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 30427e67cdbSHristo Hristov } 30527e67cdbSHristo Hristov # endif 30627e67cdbSHristo Hristov default: 30727e67cdbSHristo Hristov return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg); 30827e67cdbSHristo Hristov } 30927e67cdbSHristo Hristov } 31027e67cdbSHristo Hristov 31127e67cdbSHristo Hristov // This function is user facing, so it must wrap the non-standard types of 31227e67cdbSHristo Hristov // the "variant" in a handle to stay conforming. See __arg_t for more details. 31327e67cdbSHristo Hristov template <class _Rp, class _Visitor> 31427e67cdbSHristo Hristov _LIBCPP_HIDE_FROM_ABI _Rp visit(this basic_format_arg __arg, _Visitor&& __vis) { 31527e67cdbSHristo Hristov switch (__arg.__type_) { 316ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 31727e67cdbSHristo Hristov case __format::__arg_t::__i128: { 31827e67cdbSHristo Hristov typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; 31927e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 32027e67cdbSHristo Hristov } 32127e67cdbSHristo Hristov 32227e67cdbSHristo Hristov case __format::__arg_t::__u128: { 32327e67cdbSHristo Hristov typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; 32427e67cdbSHristo Hristov return std::invoke_r<_Rp>(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 32527e67cdbSHristo Hristov } 32627e67cdbSHristo Hristov # endif 32727e67cdbSHristo Hristov default: 32827e67cdbSHristo Hristov return std::__visit_format_arg<_Rp>(std::forward<_Visitor>(__vis), __arg); 32927e67cdbSHristo Hristov } 33027e67cdbSHristo Hristov } 33127e67cdbSHristo Hristov 332ba87515fSNikolas Klauser # endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 33327e67cdbSHristo Hristov 3340922ce56SMark de Wever private: 3350922ce56SMark de Wever using char_type = typename _Context::char_type; 3360922ce56SMark de Wever 3370922ce56SMark de Wever // TODO FMT Implement constrain [format.arg]/4 3380922ce56SMark de Wever // Constraints: The template specialization 3390922ce56SMark de Wever // typename Context::template formatter_type<T> 3400922ce56SMark de Wever // meets the Formatter requirements ([formatter.requirements]). The extent 3410922ce56SMark de Wever // to which an implementation determines that the specialization meets the 3420922ce56SMark de Wever // Formatter requirements is unspecified, except that as a minimum the 3430922ce56SMark de Wever // expression 3440922ce56SMark de Wever // typename Context::template formatter_type<T>() 3450922ce56SMark de Wever // .format(declval<const T&>(), declval<Context&>()) 3460922ce56SMark de Wever // shall be well-formed when treated as an unevaluated operand. 3470922ce56SMark de Wever 3484d8268fbSMark de Wever public: 3494d8268fbSMark de Wever __basic_format_arg_value<_Context> __value_; 3500922ce56SMark de Wever __format::__arg_t __type_; 3510922ce56SMark de Wever 3524d8268fbSMark de Wever _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type, 3534d8268fbSMark de Wever __basic_format_arg_value<_Context> __value) noexcept 3544d8268fbSMark de Wever : __value_(__value), __type_(__type) {} 355ade6d0d8SMark de Wever }; 356ade6d0d8SMark de Wever 357ade6d0d8SMark de Wever template <class _Context> 358ade6d0d8SMark de Wever class _LIBCPP_TEMPLATE_VIS basic_format_arg<_Context>::handle { 359ade6d0d8SMark de Wever public: 3609783f28cSLouis Dionne _LIBCPP_HIDE_FROM_ABI void format(basic_format_parse_context<char_type>& __parse_ctx, _Context& __ctx) const { 3614d8268fbSMark de Wever __handle_.__format_(__parse_ctx, __ctx, __handle_.__ptr_); 362ade6d0d8SMark de Wever } 363ade6d0d8SMark de Wever 364606e2808SMark de Wever _LIBCPP_HIDE_FROM_ABI explicit handle(typename __basic_format_arg_value<_Context>::__handle& __handle) noexcept 3654d8268fbSMark de Wever : __handle_(__handle) {} 366ade6d0d8SMark de Wever 3674d8268fbSMark de Wever private: 368606e2808SMark de Wever typename __basic_format_arg_value<_Context>::__handle& __handle_; 3690922ce56SMark de Wever }; 3700922ce56SMark de Wever 371e948cab0SMark de Wever // This function is user facing, so it must wrap the non-standard types of 372e948cab0SMark de Wever // the "variant" in a handle to stay conforming. See __arg_t for more details. 373e948cab0SMark de Wever template <class _Visitor, class _Context> 374ba87515fSNikolas Klauser # if _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 37527e67cdbSHristo Hristov _LIBCPP_DEPRECATED_IN_CXX26 37627e67cdbSHristo Hristov # endif 37727e67cdbSHristo Hristov _LIBCPP_HIDE_FROM_ABI decltype(auto) 37827e67cdbSHristo Hristov visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { 379e948cab0SMark de Wever switch (__arg.__type_) { 380ba87515fSNikolas Klauser # if _LIBCPP_HAS_INT128 381e948cab0SMark de Wever case __format::__arg_t::__i128: { 382e948cab0SMark de Wever typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; 38377a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 384e948cab0SMark de Wever } 385e948cab0SMark de Wever 386e948cab0SMark de Wever case __format::__arg_t::__u128: { 387e948cab0SMark de Wever typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; 38877a00c0dSLouis Dionne return std::invoke(std::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); 389e948cab0SMark de Wever } 390ba87515fSNikolas Klauser # endif // _LIBCPP_STD_VER >= 26 && _LIBCPP_HAS_EXPLICIT_THIS_PARAMETER 391e948cab0SMark de Wever default: 39277a00c0dSLouis Dionne return std::__visit_format_arg(std::forward<_Visitor>(__vis), __arg); 393e948cab0SMark de Wever } 394e948cab0SMark de Wever } 395e948cab0SMark de Wever 3964f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 20 3970922ce56SMark de Wever 3980922ce56SMark de Wever _LIBCPP_END_NAMESPACE_STD 3990922ce56SMark de Wever 4007b462251SLouis Dionne _LIBCPP_POP_MACROS 4017b462251SLouis Dionne 4020922ce56SMark de Wever #endif // _LIBCPP___FORMAT_FORMAT_ARG_H 403