From 0c5bb0fcf12ee6dfeb6f4c56ba0ffdc2fa6fa49e Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Sun, 21 Feb 2021 06:00:18 +0300 Subject: [PATCH 1/3] fix fallback to the runtime API, add FMT_ENABLE_FALLBACK_TO_RUNTIME_API define, add test --- include/fmt/compile.h | 61 ++++++++++++++++++++++++++++++++++++------- test/compile-test.cc | 19 ++++++++++++++ 2 files changed, 70 insertions(+), 10 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 08566a4d9447..ac1489a9d616 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -22,6 +22,10 @@ # endif #endif +#ifndef FMT_ENABLE_FALLBACK_TO_RUNTIME_API +# define FMT_ENABLE_FALLBACK_TO_RUNTIME_API 1 +#endif + FMT_BEGIN_NAMESPACE namespace detail { @@ -704,12 +708,13 @@ 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; - } +# if !FMT_ENABLE_FALLBACK_TO_RUNTIME_API + static_assert(!std::is_same, + detail::unknown_format>(), + "format string is invalid for compile-time API, " + "and fallback to runtime API is disabled"); +# endif + return result; } } #else @@ -789,7 +794,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,11 +853,26 @@ 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) { + Args&&... args) { constexpr auto compiled = detail::compile(S()); +#ifdef __cpp_if_constexpr + if constexpr (std::is_same, + detail::unknown_format>()) { + auto it = + format_to(detail::truncating_iterator(out, n), + static_cast>(S()), + std::forward(args)...); + return {it.base(), it.count()}; + } else { + auto it = format_to(detail::truncating_iterator(out, n), compiled, + std::forward(args)...); + return {it.base(), it.count()}; + } +#else auto it = format_to(detail::truncating_iterator(out, n), compiled, - args...); + std::forward(args)...); return {it.base(), it.count()}; +#endif } template diff --git a/test/compile-test.cc b/test/compile-test.cc index 6d5af50b2c10..3c377c9097c7 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -229,6 +229,25 @@ TEST(CompileTest, TextAndArg) { EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42)); } +# if FMT_ENABLE_FALLBACK_TO_RUNTIME_API +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:^4}"), + fmt::arg("name", 42)); + EXPECT_EQ(4u, result.size); + EXPECT_EQ(buffer + 4, result.out); + EXPECT_EQ(" 42 ", fmt::string_view(buffer, 4)); +} +# endif + TEST(CompileTest, Empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); } #endif From 46f2173388f0cae4d089c75f3729e69a37190d4e Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Mon, 1 Mar 2021 23:11:46 +0300 Subject: [PATCH 2/3] remove `FMT_ENABLE_FALLBACK_TO_RUNTIME_API` --- include/fmt/compile.h | 10 ---------- test/compile-test.cc | 2 -- 2 files changed, 12 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index ac1489a9d616..7832dd5cc156 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -22,10 +22,6 @@ # endif #endif -#ifndef FMT_ENABLE_FALLBACK_TO_RUNTIME_API -# define FMT_ENABLE_FALLBACK_TO_RUNTIME_API 1 -#endif - FMT_BEGIN_NAMESPACE namespace detail { @@ -708,12 +704,6 @@ constexpr auto compile(S format_str) { constexpr auto result = detail::compile_format_string, 0, 0>( format_str); -# if !FMT_ENABLE_FALLBACK_TO_RUNTIME_API - static_assert(!std::is_same, - detail::unknown_format>(), - "format string is invalid for compile-time API, " - "and fallback to runtime API is disabled"); -# endif return result; } } diff --git a/test/compile-test.cc b/test/compile-test.cc index 3c377c9097c7..84b75777e8f7 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -229,7 +229,6 @@ TEST(CompileTest, TextAndArg) { EXPECT_EQ("42!", fmt::format(FMT_COMPILE("{}!"), 42)); } -# if FMT_ENABLE_FALLBACK_TO_RUNTIME_API TEST(CompileTest, UnknownFormatFallback) { EXPECT_EQ(" 42 ", fmt::format(FMT_COMPILE("{name:^4}"), fmt::arg("name", 42))); @@ -246,7 +245,6 @@ TEST(CompileTest, UnknownFormatFallback) { EXPECT_EQ(buffer + 4, result.out); EXPECT_EQ(" 42 ", fmt::string_view(buffer, 4)); } -# endif TEST(CompileTest, Empty) { EXPECT_EQ("", fmt::format(FMT_COMPILE(""))); } #endif From b2bb2cb049fd1bfa427393e63b652ca58005e431 Mon Sep 17 00:00:00 2001 From: Alexey Ochapov Date: Wed, 3 Mar 2021 20:56:40 +0300 Subject: [PATCH 3/3] 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 | 18 +----------------- test/compile-test.cc | 4 ++-- 2 files changed, 3 insertions(+), 19 deletions(-) diff --git a/include/fmt/compile.h b/include/fmt/compile.h index 7832dd5cc156..0ce654c424d3 100644 --- a/include/fmt/compile.h +++ b/include/fmt/compile.h @@ -844,25 +844,9 @@ template ::value)> format_to_n_result format_to_n(OutputIt out, size_t n, const S&, Args&&... args) { - constexpr auto compiled = detail::compile(S()); -#ifdef __cpp_if_constexpr - if constexpr (std::is_same, - detail::unknown_format>()) { - auto it = - format_to(detail::truncating_iterator(out, n), - static_cast>(S()), - std::forward(args)...); - return {it.base(), it.count()}; - } else { - auto it = format_to(detail::truncating_iterator(out, n), compiled, - std::forward(args)...); - return {it.base(), it.count()}; - } -#else - auto it = format_to(detail::truncating_iterator(out, n), compiled, + auto it = format_to(detail::truncating_iterator(out, n), S(), std::forward(args)...); return {it.base(), it.count()}; -#endif } template diff --git a/test/compile-test.cc b/test/compile-test.cc index 84b75777e8f7..6ccef2d05690 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -239,9 +239,9 @@ TEST(CompileTest, UnknownFormatFallback) { EXPECT_EQ(" 42 ", fmt::string_view(v.data(), v.size())); char buffer[4]; - auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^4}"), + auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"), fmt::arg("name", 42)); - EXPECT_EQ(4u, result.size); + EXPECT_EQ(5u, result.size); EXPECT_EQ(buffer + 4, result.out); EXPECT_EQ(" 42 ", fmt::string_view(buffer, 4)); }