diff --git a/include/fmt/ranges.h b/include/fmt/ranges.h index f387903c..0d3dfbd8 100644 --- a/include/fmt/ranges.h +++ b/include/fmt/ranges.h @@ -490,7 +490,7 @@ struct range_formatter< auto out = ctx.out(); auto it = detail::range_begin(range); auto end = detail::range_end(range); - if (is_debug) return write_debug_string(out, it, end); + if (is_debug) return write_debug_string(out, std::move(it), end); out = detail::copy(opening_bracket_, out); int i = 0; diff --git a/test/ranges-test.cc b/test/ranges-test.cc index ab94209f..1a5b5a70 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -752,17 +752,17 @@ TEST(ranges_test, std_istream_iterator_join) { EXPECT_EQ("1, 2, 3, 4, 5", fmt::format("{}", fmt::join(first, last, ", "))); } -TEST(ranges_test, movable_only_istream_iter_join) { - // Mirrors C++20 std::ranges::basic_istream_view::iterator. - struct noncopyable_istream_iterator : std::istream_iterator { - explicit noncopyable_istream_iterator(std::istringstream& iss) - : std::istream_iterator{iss} {} - noncopyable_istream_iterator(const noncopyable_istream_iterator&) = delete; - noncopyable_istream_iterator(noncopyable_istream_iterator&&) = default; - }; - static_assert( - !std::is_copy_constructible::value, ""); +// Mirrors C++20 std::ranges::basic_istream_view::iterator. +struct noncopyable_istream_iterator : std::istream_iterator { + using base = std::istream_iterator; + explicit noncopyable_istream_iterator(std::istringstream& iss) : base{iss} {} + noncopyable_istream_iterator(const noncopyable_istream_iterator&) = delete; + noncopyable_istream_iterator(noncopyable_istream_iterator&&) = default; +}; +static_assert(!std::is_copy_constructible::value, + ""); +TEST(ranges_test, movable_only_istream_iter_join) { auto&& iss = std::istringstream("1 2 3 4 5"); auto first = noncopyable_istream_iterator(iss); auto last = std::istream_iterator(); @@ -770,6 +770,18 @@ TEST(ranges_test, movable_only_istream_iter_join) { fmt::format("{}", fmt::join(std::move(first), last, ", "))); } +struct movable_iter_range { + std::istringstream iss{"1 2 3 4 5"}; + noncopyable_istream_iterator begin() { + return noncopyable_istream_iterator{iss}; + } + std::istream_iterator end() { return {}; } +}; + +TEST(ranges_test, movable_only_istream_iter_join2) { + EXPECT_EQ("[1, 2, 3, 4, 5]", fmt::format("{}", movable_iter_range{})); +} + struct not_range { void begin() const {} void end() const {}