@@ -202,6 +202,31 @@ template <size_t N>
202
202
using make_index_sequence = make_integer_sequence<size_t , N>;
203
203
#endif
204
204
205
+ template <typename T>
206
+ using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
207
+
208
+ template <typename T, typename C, bool = is_tuple_like_<T>::value>
209
+ class is_tuple_formattable_ {
210
+ public:
211
+ static constexpr const bool value = false ;
212
+ };
213
+ template <typename T, typename C> class is_tuple_formattable_ <T, C, true > {
214
+ template <std::size_t ... I>
215
+ static std::true_type check2 (index_sequence<I...>,
216
+ integer_sequence<bool , (I == I)...>);
217
+ static std::false_type check2 (...);
218
+ template <std::size_t ... I>
219
+ static decltype (check2(
220
+ index_sequence<I...>{},
221
+ integer_sequence<
222
+ bool , (is_formattable<typename std::tuple_element<I, T>::type,
223
+ C>::value)...>{})) check(index_sequence<I...>);
224
+
225
+ public:
226
+ static constexpr const bool value =
227
+ decltype (check(tuple_index_sequence<T>{}))::value;
228
+ };
229
+
205
230
template <class Tuple , class F , size_t ... Is>
206
231
void for_each (index_sequence<Is...>, Tuple&& tup, F&& f) noexcept {
207
232
using std::get;
@@ -283,8 +308,15 @@ template <typename T> struct is_tuple_like {
283
308
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
284
309
};
285
310
311
+ template <typename T, typename C> struct is_tuple_formattable {
312
+ static constexpr const bool value =
313
+ detail::is_tuple_formattable_<T, C>::value;
314
+ };
315
+
286
316
template <typename TupleT, typename Char>
287
- struct formatter <TupleT, Char, enable_if_t <fmt::is_tuple_like<TupleT>::value>> {
317
+ struct formatter <TupleT, Char,
318
+ enable_if_t <fmt::is_tuple_like<TupleT>::value &&
319
+ fmt::is_tuple_formattable<TupleT, Char>::value>> {
288
320
private:
289
321
// C++11 generic lambda for format().
290
322
template <typename FormatContext> struct format_each {
0 commit comments