diff options
Diffstat (limited to 'libcxx/include/__format/format_arg.h')
| -rw-r--r-- | libcxx/include/__format/format_arg.h | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/libcxx/include/__format/format_arg.h b/libcxx/include/__format/format_arg.h index 4f93024b7c69..771a03ff2fa9 100644 --- a/libcxx/include/__format/format_arg.h +++ b/libcxx/include/__format/format_arg.h @@ -45,16 +45,22 @@ namespace __format { /// It could be packed in 4-bits but that means a new type directly becomes an /// ABI break. The packed type is 64-bit so this reduces the maximum number of /// packed elements from 16 to 12. +/// +/// @note Some members of this enum are an extension. These extensions need +/// special behaviour in visit_format_arg. There they need to be wrapped in a +/// handle to satisfy the user observable behaviour. The internal function +/// __visit_format_arg doesn't do this wrapping. So in the format functions +/// this function is used to avoid unneeded overhead. enum class _LIBCPP_ENUM_VIS __arg_t : uint8_t { __none, __boolean, __char_type, __int, __long_long, - __i128, + __i128, // extension __unsigned, __unsigned_long_long, - __u128, + __u128, // extension __float, __double, __long_double, @@ -85,9 +91,11 @@ constexpr __arg_t __get_packed_type(uint64_t __types, size_t __id) { } // namespace __format +// This function is not user obervable, so it can directly use the non-standard +// types of the "variant". See __arg_t for more details. template <class _Visitor, class _Context> -_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) visit_format_arg(_Visitor&& __vis, - basic_format_arg<_Context> __arg) { +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +__visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { switch (__arg.__type_) { case __format::__arg_t::__none: return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), __arg.__value_.__monostate_); @@ -153,7 +161,7 @@ public: using _Dp = remove_cvref_t<_Tp>; using _Formatter = typename _Context::template formatter_type<_Dp>; constexpr bool __const_formattable = - requires { _Formatter().format(declval<const _Dp&>(), declval<_Context&>()); }; + requires { _Formatter().format(std::declval<const _Dp&>(), std::declval<_Context&>()); }; using _Qp = conditional_t<__const_formattable, const _Dp, _Dp>; static_assert(__const_formattable || !is_const_v<remove_reference_t<_Tp>>, "Mandated by [format.arg]/18"); @@ -265,6 +273,28 @@ private: typename __basic_format_arg_value<_Context>::__handle& __handle_; }; +// This function is user facing, so it must wrap the non-standard types of +// the "variant" in a handle to stay conforming. See __arg_t for more details. +template <class _Visitor, class _Context> +_LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT decltype(auto) +visit_format_arg(_Visitor&& __vis, basic_format_arg<_Context> __arg) { + switch (__arg.__type_) { +# ifndef _LIBCPP_HAS_NO_INT128 + case __format::__arg_t::__i128: { + typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__i128_}; + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); + } + + case __format::__arg_t::__u128: { + typename __basic_format_arg_value<_Context>::__handle __h{__arg.__value_.__u128_}; + return _VSTD::invoke(_VSTD::forward<_Visitor>(__vis), typename basic_format_arg<_Context>::handle{__h}); + } +# endif + default: + return _VSTD::__visit_format_arg(_VSTD::forward<_Visitor>(__vis), __arg); + } +} + #endif //_LIBCPP_STD_VER > 17 _LIBCPP_END_NAMESPACE_STD |
