From 684b5b0e40d1322cf7e489dac1233a1539ba949b Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Thu, 4 Mar 2021 18:20:57 +0300 Subject: [PATCH] Fix fallback to runtime API from compile-time API (#2143) * fix fallback to the runtime API, add FMT_ENABLE_FALLBACK_TO_RUNTIME_API define, add test * remove `FMT_ENABLE_FALLBACK_TO_RUNTIME_API` * pass format string to format_to() inside format_to_n() in compile-time API instead of compiling it inside format_to_n(), to eliminate code duplication --- include/fmt/compile.h | 39 +++++++++++++++++++++++++++------------ test/compile-test.cc | 17 +++++++++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 08566a4d..0ce654c4 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -704,12 +704,7 @@ constexpr auto compile(S format_str) { constexpr auto result = detail::compile_format_string, 0, 0>( format_str); - if constexpr (std::is_same, - detail::unknown_format>()) { - return detail::compiled_format(to_string_view(format_str)); - } else { - return result; - } + return result; } } #else @@ -789,7 +784,17 @@ FMT_INLINE std::basic_string format(const S&, } #endif constexpr auto compiled = detail::compile(S()); +#ifdef __cpp_if_constexpr + if constexpr (std::is_same, + detail::unknown_format>()) { + return format(static_cast>(S()), + std::forward(args)...); + } else { + return format(compiled, std::forward(args)...); + } +#else return format(compiled, std::forward(args)...); +#endif } template ::value)> -FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, const Args&... args) { +FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { constexpr auto compiled = detail::compile(S()); - return format_to(out, compiled, args...); +#ifdef __cpp_if_constexpr + if constexpr (std::is_same, + detail::unknown_format>()) { + return format_to(out, + static_cast>(S()), + std::forward(args)...); + } else { + return format_to(out, compiled, std::forward(args)...); + } +#else + return format_to(out, compiled, std::forward(args)...); +#endif } template @@ -827,10 +843,9 @@ auto format_to_n(OutputIt out, size_t n, const CompiledFormat& cf, template ::value)> format_to_n_result format_to_n(OutputIt out, size_t n, const S&, - const Args&... args) { - constexpr auto compiled = detail::compile(S()); - auto it = format_to(detail::truncating_iterator(out, n), compiled, - args...); + Args&&... args) { + auto it = format_to(detail::truncating_iterator(out, n), S(), + std::forward(args)...); return {it.base(), it.count()}; } diff --git a/test/compile-test.cc b/test/compile-test.cc index 6d5af50b..6ccef2d0 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -229,6 +229,23 @@ TEST(CompileTest, TextAndArg) { EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42)); } +TEST(CompileTest, UnknownFormatFallback) { + EXPECT_EQ(" 42 ", + fmt::format(FMT_COMPILE("{name:^4}"), fmt::arg("name", 42))); + + std::vector v; + fmt::format_to(std::back_inserter(v), FMT_COMPILE("{name:^4}"), + fmt::arg("name", 42)); + EXPECT_EQ(" 42 ", fmt::string_view(v.data(), v.size())); + + char buffer[4]; + auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"), + fmt::arg("name", 42)); + EXPECT_EQ(5u, result.size); + EXPECT_EQ(buffer + 4, result.out); + EXPECT_EQ(" 42 ", fmt::string_view(buffer, 4)); +} + TEST(CompileTest, Empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); } #endif