Skip to content

Commit

Permalink
Fix usage with std::generator (#4057)
Browse files Browse the repository at this point in the history
Fixes #4053
  • Loading branch information
Arghnews authored Jul 9, 2024
1 parent ccea338 commit e60ff50
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 11 deletions.
2 changes: 1 addition & 1 deletion include/fmt/ranges.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

This comment has been minimized.

Copy link
@Dani-Hub

Dani-Hub Jul 9, 2024

Contributor

Problem seems to be that in line 493 the iterator it is moved into the call of write_debug_string, but in line L500 the moved-from iterator is referred to. I think the additional write_debug_string call requires it to be copyable.

This comment has been minimized.

Copy link
@vitaut

vitaut Jul 9, 2024

Contributor

I don't think it's a problem because there is a return here so L500 is not reached after move.

This comment has been minimized.

Copy link
@Dani-Hub

Dani-Hub Jul 9, 2024

Contributor

You are right, I missed the return - thanks for clarifying!


out = detail::copy<Char>(opening_bracket_, out);
int i = 0;
Expand Down
32 changes: 22 additions & 10 deletions test/ranges-test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -752,24 +752,36 @@ 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<int> {
explicit noncopyable_istream_iterator(std::istringstream& iss)
: std::istream_iterator<int>{iss} {}
noncopyable_istream_iterator(const noncopyable_istream_iterator&) = delete;
noncopyable_istream_iterator(noncopyable_istream_iterator&&) = default;
};
static_assert(
!std::is_copy_constructible<noncopyable_istream_iterator>::value, "");
// Mirrors C++20 std::ranges::basic_istream_view::iterator.
struct noncopyable_istream_iterator : std::istream_iterator<int> {
using base = std::istream_iterator<int>;
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<noncopyable_istream_iterator>::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<int>();
EXPECT_EQ("1, 2, 3, 4, 5",
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<int> 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 {}
Expand Down

0 comments on commit e60ff50

Please sign in to comment.