From 028f22775202a6a94d2346a4f7f179978bf9626f Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 31 Oct 2021 08:09:32 -0700 Subject: [PATCH] Handle implicit conversions in write --- include/fmt/format.h | 36 +++++++++++++++++++++++------------- test/format-test.cc | 17 ++++++++++++----- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index 558f23f5f264..c4c9321dc95c 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -42,7 +42,7 @@ #include // std::swap #ifdef __cpp_lib_bit_cast -#include // std::bitcast +# include // std::bitcast #endif #include "core.h" @@ -1720,7 +1720,7 @@ inline auto write_significand(Char* out, UInt significand, int significand_size, out += significand_size + 1; Char* end = out; int floating_size = significand_size - integral_size; - for(int i = floating_size / 2; i > 0; --i) { + for (int i = floating_size / 2; i > 0; --i) { out -= 2; copy2(out, digits2(significand % 100)); significand /= 100; @@ -2082,7 +2082,7 @@ FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { return base_iterator(out, it); } -// FMT_ENABLE_IF() condition separated to workaround MSVC bug +// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. template < typename Char, typename OutputIt, typename T, bool check = @@ -2133,18 +2133,28 @@ auto write(OutputIt out, const T* value, return write_ptr(out, to_uintptr(value), &specs); } -template -FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> - typename std::enable_if< - mapped_type_constant>::value == - type::custom_type, - OutputIt>::type { - using context_type = basic_format_context; +// A write overload that handles implicit conversions. +template > +FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t< + std::is_class::value && !is_string::value && + !std::is_same::value && + !std::is_same().map(value))>::value, + OutputIt> { + return write(out, arg_mapper().map(value)); +} + +template > +FMT_CONSTEXPR auto write(OutputIt out, const T& value) + -> enable_if_t::value == type::custom_type, + OutputIt> { using formatter_type = - conditional_t::value, - typename context_type::template formatter_type, + conditional_t::value, + typename Context::template formatter_type, fallback_formatter>; - context_type ctx(out, {}, {}); + auto ctx = Context(out, {}, {}); return formatter_type().format(value, ctx); } diff --git a/test/format-test.cc b/test/format-test.cc index 41303c9374a2..f3c2eca400f8 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -1820,13 +1820,20 @@ struct formatter : formatter { }; FMT_END_NAMESPACE +struct convertible_to_int { + operator int() const { return value; } + + int value = 42; +}; + TEST(format_test, to_string) { - EXPECT_EQ("42", fmt::to_string(42)); - EXPECT_EQ("0x1234", fmt::to_string(reinterpret_cast(0x1234))); - EXPECT_EQ("foo", fmt::to_string(adl_test::fmt::detail::foo())); + EXPECT_EQ(fmt::to_string(42), "42"); + EXPECT_EQ(fmt::to_string(reinterpret_cast(0x1234)), "0x1234"); + EXPECT_EQ(fmt::to_string(adl_test::fmt::detail::foo()), "foo"); + EXPECT_EQ(fmt::to_string(convertible_to_int()), "42"); - enum test_enum2 : unsigned char { test_value }; - EXPECT_EQ("0", fmt::to_string(test_value)); + enum foo : unsigned char { zero }; + EXPECT_EQ(fmt::to_string(zero), "0"); } TEST(format_test, output_iterators) {