-
Notifications
You must be signed in to change notification settings - Fork 258
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] Need decltype(auto)
for perfect backwarding
#876
Comments
An alternative is to change back to |
Yet another alternative is to change back to |
Moving the comment thread from #921 here: Thanks! Sorry for the lag. It seems like the motivation overlaps with the later discussion in #714 which starts to add Perhaps this and #876 are underscoring that there need to be three (not two) return styles, which has come up in my mind several times before:
What do you think? That would bottom out on both #714 and #876, and be instead of this PR? (*) There's a longer story here: For many years, the best candidate names I've considered for "in/out" parameters are
I liked the idea of trying to make the return styles be a subset of the parameter styles, but maybe it's time to reconsider that it doesn't quite work. If we keep Brainstorming... Naming is hard.
The question is that just as for parameters there's a distinction between I suspect that these two were conflated instead of being supported separately might have been a contributing factor to the back-and-forth about the
I think this was my last strawman: #714 (comment) If we add a third return style I'll take another pass over the table. |
I think I understand the problem. We have:
Reusing |
Thanks -- the way you phrased this is important:
You might have just put your finger on something I was missing about I was fixated on there being no "in" data flow part in a return, so that "in" didn't make sense, and always hit a wall with that. But when you state it as above, now I see maybe it is symmetric after all. Let me try to phrase it the way you did:
How does that sound? Then we have for parameters (quoting the docs, which I just tweaked to emphasize it's about what "the function" can do):
And the updated model and description for return values could be a subset that includes
What do you think? I need to sleep on it, but this may mean |
For |
We have |
I thought that was spelled as
Complementary to the above reasoning, the caller can only read from it. |
We do have that, and it would mean the same for return values and thus directly address the string However, combining I've been resisting changing Strawman 1: Musing aloud about
|
|
I like it, but...
One is |
Quick thought about making it more obvious that these are modifiers to the base behavior, and just modify the method of passing and that it doesn't modify that you get an implicitly const parameter: |
The title of that commit said One way could be to just spell returning by const references as But I feel cpp2 is just reinventing references all over again with different spelling. The improvement that the original paper promised has now diminished to just names. Maybe this is a good time to rethink the parameter kinds from ground up now that there's plenty of experience of using them? |
The original premise was that references were intended only for parameter passing and return types, and so keeping them in parameter passing and return types with different names still aligns with that, I think. |
Cpp2 could do that by simply rejecting references outside of parameter lists. |
@hsutter Since there are not supposed to be local references, what is your expectation for how we use the
Yes, but that doesn't make them any more learnable.
If you reduce the number of kinds, you reduce the expressiveness and capability, unless there are redundant ones in cpp1 that can be merged (which happened), or ones in cpp1 that should never be used and are removed (which also happened). The The addition of The removal of const rvalue references is intentional, as they are redundant with const lvalue references. cpp1 has 7 styles if you consider value and const value as different (they are different on the callee side, not on the caller side): value, const value, lvalue reference, const lvalue reference, rvalue reference, const rvalue reference, universal reference cpp2 has 6 styles |
There's If this comment is implemented, there will be
I'm not against |
I really like the idea of @abhinav00 I would be also in favor of reducing the number of passing and return kinds. If Cpp2 would be a new language, this could be done without any problems. Since we need to be compatible with Cpp1 and transpile to Cpp1 there is probably no way around it. |
I was basing my count of 6 on this, plus restoring
in (in_copy + in_ref or The forward_ref and perhaps forward_copy are solely return styles. |
Interim mea culpa: Ignore most of what I wrote above, which is confusing the issue because I just forgot about problems that have already been solved. For example, no we don't need
So we already solved most of what I wrote above. The main thing I don't think is yet addressed is the deduced return type being able to be a value or not. Sorry for the noise. More (and simpler) update soon... |
Small suggestion, just use |
Catching up: Re do we need to replicate Cpp1 styles: No, never. We just need to cover the use cases using "what" not "how. The PlanI think I've got an improved simple answer:
The two ⭐'s are the cases that automatically pass/return by value or reference:
So both those should also provide a
(*) And this is still way simpler than the Cpp1 styles which cover way more than the use cases. Today in Cpp1 we have to teach (among other problems):
|
@hsutter I like that description. Another quick pass on bikeshedding of There is also the question of what we should use on the calling side to receive this |
This comment was marked as resolved.
This comment was marked as resolved.
That's because I edited the check/star symbols after initially posting... you're right, the original way was better 👍 |
Note I decided not to do an So |
I thought when I was posting last week that I had a use case for One benefit of That then made me realize that |
According to the guidelines, Directly related so slicing:
More casually related to slicing: C.21, E.15, T.81. |
Yes, and you'll still be able to write |
Makes sense.
Yes, and it would be good to provide tools to make sure users don't copy inappropriately. We are preventing it with |
Title: Need
decltype(auto)
for perfect backwarding.Description:
At first, a Cpp2
-> forward _
return-list lowered to the Cpp1 return typeauto&&
.#175 noted this was unsafe,
and commit b59f539 changed it to
decltype(auto)
.#274 noted that this makes accessors return by copy,
then commit 413de0e changed it back to
auto&&
,and commit 43cdf3e addressed some safety concerns of #175.
Now perfect backwarding doesn't work or returns a temporary.
This means we can't implement
std::invoke
or simpler equivalents.For example, implementing a simple
function_ref
: https://cpp2.godbolt.org/z/r53zfnxbT.Minimal reproducer (https://cpp2.godbolt.org/z/bjjfqEc9e):
Commands:
cppfront main.cpp2 clang++18 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -Werror=unused-result -Werror=unused-value -Werror=unused-parameter -I . main.cpp
Expected result: Perfect backwarding to work.
Actual result and error:
Cpp2 lowered to Cpp1:
See also:
this
returns non-const reference that dropsconst
#274.The text was updated successfully, but these errors were encountered: