Skip to content
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

[SUGGESTION] clarify need for move/forward #221

Closed
maddanio opened this issue Jan 12, 2023 · 9 comments
Closed

[SUGGESTION] clarify need for move/forward #221

maddanio opened this issue Jan 12, 2023 · 9 comments

Comments

@maddanio
Copy link

Can someone clarify why move and forward are needed? Seems to me in/out are statements of intent while move/forward are implementation details? Recently saw a talk about the val language and it seems they get a lot of mileage out of just in/inout/out.

@maddanio maddanio changed the title [SUGGESTION] [SUGGESTION] clarify need for move/forward Jan 12, 2023
@SebastianTroy
Copy link

SebastianTroy commented Jan 12, 2023 via email

@maddanio
Copy link
Author

Hmm, but can a move not be generated in the right place? If I say 'in' it means i want to use this value exclusively, so if it is not used elsewhere anymore the move could be generated, no? In general I am wondering if things like in/inout/out become available isnt that enough to infer the right action, and forward/move become cumbersome details?

@SebastianTroy
Copy link

I just reread this paper by HSutter himself

If I understand your concern, you're saying that "move" is a subset of "in", which I think it is, some "in" parameters may even be optimised to "move" at compile time, but I think that it is important to give the function writer the choice to force a move, which "in" can't do.

I could be wrong about this but:
"forward" is only used in templates, and I believe it is a way of not just templating the type, but also templating the "in". "inout", "out", "move" part as well, though I think it can only mean "in" or "move". So if "in" and "move" are collapsed to just "in", then I guess "forward" becomes obsolete too?

@helmesjo
Copy link
Contributor

Without having a good insight into cppfront and the decisions regarding move so far, wouldn't it be a good opportunity to default to move and issue error if it's used in the same scope after being moved from (I guess always except if it's passed to an out parameter)?
(I just scimmed through above so maybe it was already discussed)

@hsutter
Copy link
Owner

hsutter commented Jan 12, 2023

Seems to me in/out are statements of intent while move/forward are implementation details?

So if "in" and "move" are collapsed to just "in", then I guess "forward" becomes obsolete too?

I attempt to answer this in paper d0708, particularly the summary table in section 1.1.2. See also the other resources in README.md > 2020: Parameter passing.

The short answer is that writing in vs. move isn't leaking implementation detail, it's expressing the intent of the callee which affects what the caller can expect:

  • An in parameter says that the callee will read but not modify the object (it is const inside the callee), and the caller can pass any initialized object and expect that it won't be modified by that call.
  • A move parameter says that the callee will consume the value of the argument by moving it out, and the caller can pass any rvalue (but not an an lvalue, a named object where this is not its definite last use). That's important because if the caller is trying to pass a named variable (which means they could try to use the name again on the very next line), the caller needs to know they shouldn't try to use the object's value again before first resetting it to a new value... and because a move parameter accepts only an rvalue, the caller who tries to pass an lvalue will fail and has to explicitly write move to say 'trust me, treat this as an rvalue' to make it clear they know what they're getting into.

And forward is very special -- it's for wrapper functions, and specially tracks the argument's const-ness (const or non-const) and value category (lvalue vs rvalue) so that when the callee then uses the parameter those properties are passed along, including that the callee body that passes the parameter to some other function will do different overload resolution depending on whether the argument is const or not and/or an lvalue or not.

"forward" is only used in templates,

That's effectively true in Cpp1, and templates are an implementation detail in Cpp2. But one of the things Cpp2 generalizes is that you can easily forward a concrete type too (that is not template parameter type; that's technically possible in Cpp1 by hand-writing the same pattern cppfront emits, but it's difficult and AFAIK no one does it). This is implemented, and there's a live demo in this 1-min clip of the CppCon 2022 talk that shows how it works.

@hsutter hsutter closed this as completed Jan 12, 2023
@jcanizales
Copy link

jcanizales commented Jan 13, 2023

Thank you for the summary! (And to @maddanio for asking)

@maddanio
Copy link
Author

Yes Thanks a lot!

@AbhinavK00
Copy link

Val also has move parameters, they call it "sink". Just saying

@maddanio
Copy link
Author

ah, right, yah, sorry, guess I should have read more before asking...sorry again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants