16#include "../microfmt.hpp"
28template <
typename T>
using remove_cvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
30template <
typename T,
typename =
void>
struct has_data : std::false_type {};
32template <
typename T>
struct has_data<T, std::void_t<decltype(std::declval<T &>().data())>> : std::true_type {};
39template <
typename T,
typename =
void>
struct is_tuple_like : std::false_type {};
42struct is_tuple_like<T, std::void_t<decltype(std::tuple_size<remove_cvref_t<T>>::value)>>
43 : std::integral_constant<bool, !has_data<remove_cvref_t<T>>::value> {};
45template <
typename Tuple,
size_t... Is>
47 std::index_sequence<Is...>)
noexcept {
49 auto format_elem = [&idx, &out, &sep, &spec](
const auto &elem)
noexcept {
60 (format_elem(std::get<Is>(t)), ...);
71template <
typename T>
struct formatter<T, std::enable_if_t<detail::is_tuple_like<T>::value>> {
73 char close_delim{
')'};
74 microfmt::string_view separator{
", "};
75 microfmt::string_view forwarded_spec{
""};
78 auto spec = ctx.spec();
84 if (spec[0] ==
'b' || spec[0] ==
'B') {
88 }
else if (spec[0] ==
'c' || spec[0] ==
'C') {
92 }
else if (spec[0] ==
'n' || spec[0] ==
'N') {
96 }
else if (spec[0] ==
'p' || spec[0] ==
'P') {
102 forwarded_spec = spec.substr(i);
106 if (open_delim !=
'\0') {
110 constexpr size_t N = std::tuple_size<detail::remove_cvref_t<T>>::value;
111 if constexpr (N > 0) {
115 if (close_delim !=
'\0') {
116 out.put(close_delim);
Definition microfmt.hpp:881
typename std::remove_cv< typename std::remove_reference< T >::type >::type remove_cvref_t
Definition tuple.hpp:28
void format_tuple_impl(const Tuple &t, const sink &out, microfmt::string_view sep, microfmt::string_view spec, std::index_sequence< Is... >) noexcept
Definition tuple.hpp:46
reloco::sink sink
Type-erased, zero-allocation output sink.
Definition microfmt.hpp:46