From 64a55ba2141b52f91ac6b290d406272e7500c8ad Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Mon, 21 Oct 2024 20:14:21 +0500 Subject: [PATCH 1/2] Implement fmt::format_to into std::vector Signed-off-by: Vladislav Shchapov --- include/fmt/base.h | 27 +++++++++++++++++++++++++-- test/compile-test.cc | 11 ++++++++--- 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index 4d846f44f0fe..bdb4f5e9c220 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1973,15 +1973,38 @@ template class counting_buffer : public buffer { template struct is_back_insert_iterator> : std::true_type {}; +template +struct has_container_append : std::false_type {}; +template +struct has_container_append().append( + std::declval(), std::declval()))>> + : std::true_type {}; + // An optimized version of std::copy with the output value type (T). -template ::value)> +template < + typename T, typename InputIt, typename OutputIt, + FMT_ENABLE_IF( + is_back_insert_iterator::value&& has_container_append< + decltype(get_container(std::declval())), InputIt>::value)> FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { get_container(out).append(begin, end); return out; } +template ::value && + !has_container_append< + decltype(get_container(std::declval())), + InputIt>::value)> +FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) + -> OutputIt { + auto& c = get_container(out); + c.insert(c.end(), begin, end); + return out; +} + template ::value)> FMT_CONSTEXPR auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { diff --git a/test/compile-test.cc b/test/compile-test.cc index e3a5dca2bc7c..043588e49050 100644 --- a/test/compile-test.cc +++ b/test/compile-test.cc @@ -8,6 +8,7 @@ #include "fmt/compile.h" #include +#include #include "fmt/chrono.h" #include "fmt/ranges.h" @@ -229,10 +230,14 @@ TEST(compile_test, unknown_format_fallback) { 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}"), + std::vector v1; + fmt::format_to(std::back_inserter(v1), FMT_COMPILE("{}"), 42); + EXPECT_EQ("42", fmt::string_view(v1.data(), v1.size())); + + std::vector v2; + fmt::format_to(std::back_inserter(v2), FMT_COMPILE("{name:^4}"), fmt::arg("name", 42)); - EXPECT_EQ(" 42 ", fmt::string_view(v.data(), v.size())); + EXPECT_EQ(" 42 ", fmt::string_view(v2.data(), v2.size())); char buffer[4]; auto result = fmt::format_to_n(buffer, 4, FMT_COMPILE("{name:^5}"), From ca497db44c69e92b652a551f16abbf65bf1a492e Mon Sep 17 00:00:00 2001 From: Vladislav Shchapov Date: Thu, 24 Oct 2024 01:18:09 +0500 Subject: [PATCH 2/2] Move get_container to the trait Signed-off-by: Vladislav Shchapov --- include/fmt/base.h | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/include/fmt/base.h b/include/fmt/base.h index bdb4f5e9c220..169b08619c90 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -1973,20 +1973,20 @@ template class counting_buffer : public buffer { template struct is_back_insert_iterator> : std::true_type {}; -template -struct has_container_append : std::false_type {}; -template -struct has_container_append().append( - std::declval(), std::declval()))>> - : std::true_type {}; +template +struct has_back_insert_iterator_container_append : std::false_type {}; +template +struct has_back_insert_iterator_container_append< + OutputIt, InputIt, + void_t()) + .append(std::declval(), + std::declval()))>> : std::true_type {}; // An optimized version of std::copy with the output value type (T). -template < - typename T, typename InputIt, typename OutputIt, - FMT_ENABLE_IF( - is_back_insert_iterator::value&& has_container_append< - decltype(get_container(std::declval())), InputIt>::value)> +template ::value&& + has_back_insert_iterator_container_append< + OutputIt, InputIt>::value)> FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { get_container(out).append(begin, end); @@ -1995,9 +1995,8 @@ FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) template ::value && - !has_container_append< - decltype(get_container(std::declval())), - InputIt>::value)> + !has_back_insert_iterator_container_append< + OutputIt, InputIt>::value)> FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt { auto& c = get_container(out);