Fix is_formattable for tuple-like types.

This commit is contained in:
John Eivind Helset 2022-06-18 16:53:00 +02:00
parent eaa8efb950
commit 0203853868
3 changed files with 39 additions and 1 deletions

View File

@ -202,6 +202,24 @@ template <size_t N>
using make_index_sequence = make_integer_sequence<size_t, N>;
#endif
template <typename T>
using tuple_index_sequence = make_index_sequence<std::tuple_size_v<T>>;
template <typename T, bool = is_tuple_like_<T>::value>
struct is_tuple_formattable_ {
static constexpr const bool value = false;
};
template <typename T> struct is_tuple_formattable_<T, true> {
template <std::size_t... I>
static std::integral_constant<
bool, (fmt::is_formattable<std::tuple_element_t<I, T>>::value && ...)>
check(index_sequence<I...>);
public:
static constexpr const bool value =
decltype(check(tuple_index_sequence<T>{}))::value;
};
template <class Tuple, class F, size_t... Is>
void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) noexcept {
using std::get;
@ -283,8 +301,14 @@ template <typename T> struct is_tuple_like {
detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
};
template <typename T> struct is_tuple_formattable {
static constexpr const bool value = detail::is_tuple_formattable_<T>::value;
};
template <typename TupleT, typename Char>
struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> {
struct formatter<TupleT, Char,
enable_if_t<fmt::is_tuple_like<TupleT>::value &&
fmt::is_tuple_formattable<TupleT>::value>> {
private:
// C++11 generic lambda for format().
template <typename FormatContext> struct format_each {

View File

@ -90,6 +90,18 @@ TEST(ranges_test, format_tuple) {
std::tuple<int, float, std::string, char>(42, 1.5f, "this is tuple", 'i');
EXPECT_EQ(fmt::format("{}", t), "(42, 1.5, \"this is tuple\", 'i')");
EXPECT_EQ(fmt::format("{}", std::tuple<>()), "()");
enum class noformatenum{b};
struct noformatstruct{};
EXPECT_TRUE((fmt::is_formattable<std::tuple<>>::value));
EXPECT_FALSE((fmt::is_formattable<noformatenum>::value));
EXPECT_FALSE((fmt::is_formattable<noformatstruct>::value));
EXPECT_FALSE((fmt::is_formattable<std::tuple<noformatenum>>::value));
EXPECT_FALSE((fmt::is_formattable<std::tuple<noformatstruct>>::value));
EXPECT_FALSE((fmt::is_formattable<std::tuple<noformatstruct,int>>::value));
EXPECT_FALSE((fmt::is_formattable<std::tuple<int,noformatenum>>::value));
EXPECT_FALSE((fmt::is_formattable<std::tuple<noformatstruct,noformatenum>>::value));
EXPECT_TRUE((fmt::is_formattable<std::tuple<int,float>>::value));
}
#ifdef FMT_RANGES_TEST_ENABLE_FORMAT_STRUCT

View File

@ -315,10 +315,12 @@ TEST(xchar_test, ostream) {
#endif
}
#ifdef FMT_XCHAR_TEST_ENABLE_FORMAT_MAP
TEST(xchar_test, format_map) {
auto m = std::map<std::wstring, int>{{L"one", 1}, {L"t\"wo", 2}};
EXPECT_EQ(fmt::format(L"{}", m), L"{\"one\": 1, \"t\\\"wo\": 2}");
}
#endif
TEST(xchar_test, escape_string) {
using vec = std::vector<std::wstring>;