From bdcf4355d0b27210348d5ba783754d425eca4ab6 Mon Sep 17 00:00:00 2001 From: Victor Zverovich Date: Sun, 5 Jan 2020 09:28:21 -1000 Subject: [PATCH] Fix handling of output iterators in format_to_n (#1506) --- include/fmt/format.h | 6 +++--- test/format-test.cc | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/include/fmt/format.h b/include/fmt/format.h index df387422400f0..bdaadfae5351c 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -445,13 +445,13 @@ template class truncating_iterator : public truncating_iterator_base { public: - using value_type = typename OutputIt::container_type::value_type; + using value_type = void; truncating_iterator(OutputIt out, std::size_t limit) : truncating_iterator_base(out, limit) {} - truncating_iterator& operator=(value_type val) { - if (this->count_++ < this->limit_) this->out_ = val; + template truncating_iterator& operator=(T val) { + if (this->count_++ < this->limit_) *this->out_++ = val; return *this; } diff --git a/test/format-test.cc b/test/format-test.cc index cf4e764d31f4e..76f5710651f14 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2080,6 +2080,33 @@ TEST(FormatTest, WideFormatToN) { EXPECT_EQ(L"BC x", fmt::wstring_view(buffer, 4)); } +struct test_output_iterator { + char* data; + + using iterator_category = std::output_iterator_tag; + using value_type = void; + using difference_type = void; + using pointer = void; + using reference = void; + + test_output_iterator& operator++() { + ++data; + return *this; + } + test_output_iterator operator++(int) { + auto tmp = *this; + ++data; + return tmp; + } + char& operator*() { return *data; } +}; + +TEST(FormatTest, FormatToNOutputIterator) { + char buf[10] = {}; + fmt::format_to_n(test_output_iterator{buf}, 10, "{}", 42); + EXPECT_STREQ(buf, "42"); +} + #if FMT_USE_CONSTEXPR struct test_arg_id_handler { enum result { NONE, EMPTY, INDEX, NAME, ERROR };