|
17 | 17 | #include <type_traits> |
18 | 18 | #include <utility> |
19 | 19 |
|
| 20 | +#if __STDC_HOSTED__ |
| 21 | +#include <format> |
| 22 | +#endif // __STDC_HOSTED__ |
| 23 | + |
20 | 24 | #ifdef __cpp_rtti |
21 | 25 | #include <optional> |
22 | 26 | #include <typeinfo> |
@@ -554,6 +558,10 @@ struct facade_conv_traits_impl<F, Cs...> : applicable_traits { |
554 | 558 | template <class P> |
555 | 559 | static constexpr bool conv_applicable_ptr = |
556 | 560 | (conv_traits<Cs>::template applicable_ptr<P> && ...); |
| 561 | + template <bool IsDirect, class D, class O> |
| 562 | + static constexpr bool is_invocable = std::is_base_of_v<dispatcher_meta< |
| 563 | + typename overload_traits<O>::template meta_provider<IsDirect, D>>, |
| 564 | + conv_meta>; |
557 | 565 | }; |
558 | 566 | template <class F, class... Rs> |
559 | 567 | struct facade_refl_traits_impl : inapplicable_traits {}; |
@@ -1575,6 +1583,47 @@ struct sign { |
1575 | 1583 | template <std::size_t N> |
1576 | 1584 | sign(const char (&str)[N]) -> sign<N>; |
1577 | 1585 |
|
| 1586 | +#if __STDC_HOSTED__ |
| 1587 | +template <class CharT> struct format_overload_traits; |
| 1588 | +template <> |
| 1589 | +struct format_overload_traits<char> |
| 1590 | + : std::type_identity<std::format_context::iterator( |
| 1591 | + std::string_view spec, std::format_context& fc) const> {}; |
| 1592 | +template <> |
| 1593 | +struct format_overload_traits<wchar_t> |
| 1594 | + : std::type_identity<std::wformat_context::iterator( |
| 1595 | + std::wstring_view spec, std::wformat_context& fc) const> {}; |
| 1596 | +template <class CharT> |
| 1597 | +using format_overload_t = typename format_overload_traits<CharT>::type; |
| 1598 | + |
| 1599 | +struct format_dispatch { |
| 1600 | + // Note: This function requires std::formatter<T, CharT> to be well-formed. |
| 1601 | + // However, the standard did not provide such facility before C++23. In the |
| 1602 | + // "required" clause of this function, std::formattable (C++23) is preferred |
| 1603 | + // when available. Otherwise, when building with C++20, we simply check |
| 1604 | + // whether std::formatter<T, CharT> is a disabled specialization of |
| 1605 | + // std::formatter by std::is_default_constructible_v as per |
| 1606 | + // [format.formatter.spec]. |
| 1607 | + template <class T, class CharT, class OutIt> |
| 1608 | + OutIt operator()(const T& self, std::basic_string_view<CharT> spec, |
| 1609 | + std::basic_format_context<OutIt, CharT>& fc) |
| 1610 | + requires( |
| 1611 | +#if defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L |
| 1612 | + std::formattable<T, CharT> |
| 1613 | +#else |
| 1614 | + std::is_default_constructible_v<std::formatter<T, CharT>> |
| 1615 | +#endif // defined(__cpp_lib_format_ranges) && __cpp_lib_format_ranges >= 202207L |
| 1616 | + ) { |
| 1617 | + std::formatter<T, CharT> impl; |
| 1618 | + { |
| 1619 | + std::basic_format_parse_context<CharT> pc{spec}; |
| 1620 | + impl.parse(pc); |
| 1621 | + } |
| 1622 | + return impl.format(self, fc); |
| 1623 | + } |
| 1624 | +}; |
| 1625 | +#endif // __STDC_HOSTED__ |
| 1626 | + |
1578 | 1627 | #ifdef __cpp_rtti |
1579 | 1628 | struct proxy_cast_context { |
1580 | 1629 | const std::type_info* type_ptr; |
@@ -1737,6 +1786,12 @@ struct basic_facade_builder { |
1737 | 1786 | template <constraint_level CL> |
1738 | 1787 | using support_destruction = basic_facade_builder< |
1739 | 1788 | Cs, Rs, details::make_destructible(C, CL)>; |
| 1789 | +#if __STDC_HOSTED__ |
| 1790 | + using support_format = add_convention< |
| 1791 | + details::format_dispatch, details::format_overload_t<char>>; |
| 1792 | + using support_wformat = add_convention< |
| 1793 | + details::format_dispatch, details::format_overload_t<wchar_t>>; |
| 1794 | +#endif // __STDC_HOSTED__ |
1740 | 1795 | #ifdef __cpp_rtti |
1741 | 1796 | using support_indirect_rtti = basic_facade_builder< |
1742 | 1797 | details::add_conv_t<Cs, details::conv_impl<false, |
@@ -2108,6 +2163,39 @@ ___PRO_DEBUG( \ |
2108 | 2163 |
|
2109 | 2164 | } // namespace pro |
2110 | 2165 |
|
| 2166 | +#if __STDC_HOSTED__ |
| 2167 | +namespace std { |
| 2168 | + |
| 2169 | +template <class F, class CharT> |
| 2170 | + requires(pro::details::facade_traits<F>::template is_invocable<false, |
| 2171 | + pro::details::format_dispatch, pro::details::format_overload_t<CharT>>) |
| 2172 | +struct formatter<pro::proxy_indirect_accessor<F>, CharT> { |
| 2173 | + constexpr auto parse(basic_format_parse_context<CharT>& pc) { |
| 2174 | + for (auto it = pc.begin(); it != pc.end(); ++it) { |
| 2175 | + if (*it == '}') { |
| 2176 | + spec_ = basic_string_view<CharT>{pc.begin(), it + 1}; |
| 2177 | + return it; |
| 2178 | + } |
| 2179 | + } |
| 2180 | + return pc.end(); |
| 2181 | + } |
| 2182 | + |
| 2183 | + template <class OutIt> |
| 2184 | + OutIt format(const pro::proxy_indirect_accessor<F>& ia, |
| 2185 | + basic_format_context<OutIt, CharT>& fc) const { |
| 2186 | + auto& p = pro::access_proxy<F>(ia); |
| 2187 | + if (!p.has_value()) { ___PRO_THROW(format_error{"null proxy"}); } |
| 2188 | + return pro::proxy_invoke<false, pro::details::format_dispatch, |
| 2189 | + pro::details::format_overload_t<CharT>>(p, spec_, fc); |
| 2190 | + } |
| 2191 | + |
| 2192 | + private: |
| 2193 | + basic_string_view<CharT> spec_; |
| 2194 | +}; |
| 2195 | + |
| 2196 | +} // namespace std |
| 2197 | +#endif // __STDC_HOSTED__ |
| 2198 | + |
2111 | 2199 | #undef ___PRO_THROW |
2112 | 2200 | #undef ___PRO_NO_UNIQUE_ADDRESS_ATTRIBUTE |
2113 | 2201 |
|
|
0 commit comments