-
Notifications
You must be signed in to change notification settings - Fork 260
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
[BUG] introducing adding as_const() to for-loop make it impossible to use rvalue container #234
Comments
I have tried main: () -> int = {
v : std::vector = (1,2,3);
for v do :(e) = {
std::cout << e << std::endl;
}
} Expecting that there will be a call to cppfront generates: [[nodiscard]] auto main() -> int{
std::vector v {1, 2, 3};
for ( auto&& cpp2_range = std::as_const(v); auto const& e : cpp2_range ) {
std::cout << e << std::endl;
}
} and that, of course, compiles and executes fine. |
I have played a little bit with the helper function the best I can get in a couple of minutes was: https://godbolt.org/z/dMzjovM19 |
@hsutter do you know why the following code: namespace cpp2 {
template <typename T>
[[nodiscard]] auto ensure_const_loop(T&& x) noexcept -> decltype(auto) {
if constexpr ( std::is_rvalue_reference_v<decltype(x)> ) {
return std::forward<T>(x);
} else {
return std::as_const(x);
}
}
} ends up with destroying temporary container that was passed to the function? My assumption was that forwarding temporary should end up with temporary on the return of the function. Unfortunately it is not a case - check here: https://godbolt.org/z/Tz1nh95qc |
I would not expect there to be any benefit to wrapping the target of a range based for loop in |
I agree, moving a container for use within a loop does not make much sense, since the container isn't moved anywhere, only it's elements are used. Besides, a for loop either modifies a container or accesses it's elements (or both). Modifying a last-use rvalue does not make sense, and you would not need an rvalue for const-access either, and since a loop is part of tha parent function, we are not passing the container outside the current context either. Essentially, you wouldn't do something like this:
So why would you move it into a loop? |
@switch-blade-stuff the current implementation of cppfront compiles the following code main: () -> int = {
s : std::string = "testing";
s[0] = 'a';
} to (skipping boilerplate) [[nodiscard]] auto main() -> int{
std::string s {"testing"};
cpp2::assert_in_bounds(std::move(s), 0) = 'a';
} So, it calls By saying, I report that behavior to @hsutter just to let him know that, in that case, it behaves differently than I see it usually does. |
Hmm, I would say that both of those are things that make no sense. Maybe the I was thinking "For that matter, there's no reason to do a move into a function that only takes by |
I don't know the details about how [[nodiscard]] auto main() -> int{
for ( auto&& cpp2_range = returns_a_copy(); auto const& e : std::as_const(cpp2_range) ) {
std::cout << e << std::endl;
}
}``` |
Oh nevermind, fixed as I was typing haha |
Thanks! Now fixed... on second thought using
Looks like that long-standing lifetime bug that P2644 fixes -- we finally adopted that fix two months ago in Kona, for C++23. Which BTW is another reason not to use the original |
@hsutter Should we pull out the #234 (comment) related discussion into a separate issue? |
@gregmarr Do you mean including a use that is a range-for range as a last use? |
I wonder if it is accidental that there is no move from last use of the container (when last use is in for-loop) or is it by design. |
@hsutter That, and also that this:
compiles to this:
Maybe it's fine behavior-wise, but it definitely looks weird. |
… of using `as_const`, closes hsutter#234
… of using `as_const`, closes hsutter#234
de630b9 introduce the call to
std::as_cast
when for loop usesin
passing style. That makes it fail when dealing with rvalue containers.The following code:
Generates (skipping boilerplate):
And fails to compile with an error:
The issue is that the container is an rvalue, and
std::as_const()
has explicitly deleted overload for rvalue.The quick workaround is to write a helper function that handles rvalue by forwarding it or otherwise returns results of
std::as_const
.The text was updated successfully, but these errors were encountered: