-
Notifications
You must be signed in to change notification settings - Fork 2.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fmt::join doesn't handle move-only iterators #3802
Comments
|
Or is it unrelated? |
This is a different to #3800 |
There are a couple of places in the Lines 587 to 603 in 810d175
Line 590 takes a copy of the iterator, which it then modifies. Because the It seems like we need to take the The generic range support without |
This should work. What error do you get? |
Changing the signature of template <typename FormatContext>
auto format(join_view<It, Sentinel, Char>& value,
FormatContext& ctx) const -> decltype(ctx.out()) (that is, removing the
From the last line, it seems that something is trying to pass a |
GCC gives a little more context: an error occurs in the return value of Lines 197 to 204 in 3c96084
Here, Lines 128 to 130 in 3c96084
so I guess adding the |
Looks like we need to propagate (lack of) constness during format string compilation. Currently it passes everything by |
I get a similar error without
|
Addresses issue (fmtlib#3802) For input_ranges (ie. a range with an input iterator backing it) we should not copy the iterator and should mutate the iterator on the view. For forward_ranges (or better), we can keep using them as const and make a copy of the iterator etc. This is an issue for code like: std::istringstream iss("1 2 3 4 5"); auto view = std::views::istream<int>(iss) fmt::join(std::move(view), ", ") Since the std::ranges::basic_istream_view::__iterator is not copyable And the struct formatter<join_view<It, Sentinel, Char>, Char> only has a template <typename FormatContext> auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx) const -> decltype(ctx.out()) { auto it = value.begin; Which takes the value param by const ref and copies the iterator Fix is disabling the const ref format function overload when we have an input iterator passed to our join_view, and instead then just mutate the iterator in place and use a mutable join_view&
Addresses issue (fmtlib#3802) For input_ranges (ie. a range with an input iterator backing it) we should not copy the iterator and should mutate the iterator on the view. For forward_ranges (or better), we can keep using them as const and make a copy of the iterator etc. This is an issue for code like: std::istringstream iss("1 2 3 4 5"); auto view = std::views::istream<int>(iss) fmt::join(std::move(view), ", ") Since the std::ranges::basic_istream_view::__iterator is not copyable And the struct formatter<join_view<It, Sentinel, Char>, Char> only has a template <typename FormatContext> auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx) const -> decltype(ctx.out()) { auto it = value.begin; Which takes the value param by const ref and copies the iterator Fix is disabling the const ref format function overload when we have an input iterator passed to our join_view, and instead then just mutate the iterator in place and use a mutable join_view& overload for this case
Addresses issue (fmtlib#3802) For input_ranges (ie. a range with an input iterator backing it) we should not copy the iterator and should mutate the iterator on the view. For forward_ranges (or better), we can keep using them as const and make a copy of the iterator etc. This is an issue for code like: std::istringstream iss("1 2 3 4 5"); auto view = std::views::istream<int>(iss) fmt::join(std::move(view), ", ") Since the std::ranges::basic_istream_view::__iterator is not copyable And the struct formatter<join_view<It, Sentinel, Char>, Char> only has a template <typename FormatContext> auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx) const -> decltype(ctx.out()) { auto it = value.begin; Which takes the value param by const ref and copies the iterator Fix is disabling the const ref format function overload when we have an input iterator passed to our join_view, and instead then just mutate the iterator in place and use a mutable join_view& overload for this case
If iterator not copyable mutate the underlying iterator Notably std::ranges::basic_istream_view::__iterator Addresses issue (fmtlib#3802)
If iterator not copyable mutate the underlying iterator Notably std::ranges::basic_istream_view::__iterator Addresses issue (fmtlib#3802)
If iterator not copyable mutate the underlying iterator Notably std::ranges::basic_istream_view::__iterator Addresses issue (#3802)
Fixed by #3946. |
C++20 allows iterators for input ranges to be move-only, for example
std::ranges::basic_istream_view::iterator
. Unfortunatelyfmt::join_view
copies iterators in various places, meaning it can't be used with such ranges:https://godbolt.org/z/1ndGahqb7
The text was updated successfully, but these errors were encountered: