diff --git a/include/fmt/format.h b/include/fmt/format.h index 1a76ebd4..b6924f2b 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -203,8 +203,7 @@ FMT_END_NAMESPACE // Some compilers masquerade as both MSVC and GCC-likes or otherwise support // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the // MSVC intrinsics if the clz and clzll builtins are not available. -#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && \ - !defined(FMT_BUILTIN_CTZLL) +#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL) FMT_BEGIN_NAMESPACE namespace detail { // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. @@ -2103,6 +2102,12 @@ FMT_CONSTEXPR OutputIt write(OutputIt out, basic_string_view value) { return base_iterator(out, it); } +template ::value)> +constexpr OutputIt write(OutputIt out, const T& value) { + return write(out, to_string_view(value)); +} + template ::value && !std::is_same::value && diff --git a/test/compile-test.cc b/test/compile-test.cc index fbcbfbaf..c3d31ac6 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -288,6 +288,27 @@ TEST(CompileTest, UnknownFormatFallback) { } TEST(CompileTest, Empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); } + +struct to_stringable { + friend fmt::string_view to_string_view(to_stringable) { return {}; } +}; + +FMT_BEGIN_NAMESPACE +template <> struct formatter { + auto parse(format_parse_context& ctx) const -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const to_stringable&, FormatContext& ctx) -> decltype(ctx.out()) { + return ctx.out(); + } +}; +FMT_END_NAMESPACE + +TEST(CompileTest, ToStringAndFormatter) { + fmt::format(FMT_COMPILE("{}"), to_stringable()); +} #endif #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS