-
Notifications
You must be signed in to change notification settings - Fork 771
[stmt.return] Fix the operand's conversions description #4107
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
Conversation
6414ae2
to
d5234f5
Compare
a5d8063
to
4787329
Compare
Why don't we have copy-initialization for the return value? |
4787329
to
eb9254a
Compare
Because we don't initialize values in C++. If you mean why don't we initialize the result, well, because the result is either a value, which I've already covered, or an object, which is already initialized somewhere, or function, which doesn't need initialization. For example: int& f(int& ref) { return ref; #1 }
int main()
{
int i = 0; #2
f(i);
} What does the return statement in |
We still call "int& i = x" copy-initialization, I believe. I'm not seeing a material difference to what we do for the "return" case (except for trying rvalues before lvalues in certain cases). |
Basically what I'm trying to fix is described in this comment. After #3587, [expr.call] says:
With [stmt.return] saying:
we have a sort of circularity, as described in that comment: the return statement initializes the result of its operand from the result of its operand. With my fix, [stmt.return] only determines the sequence of conversion. [expr.call] relies on it to say what is the result of a function call.
I believe, more correct would be to say that in C++ we don't initialize objects, but variables and non-static data members. And in BTW, you didn't answer what is initialized by the return statement in my code. |
I think we initialize a return value (in the broadest sense; here, it's a reference) that is then discarded. (If we were returning an object, we'd call the destructor on it when we discard it.) And we do initialize objects; there's a fresh initialization of the fresh object designated by the variable
|
A glvalue is an expression which denotes an object or function. The result of a glvalue is the |
The glvalue refers to |
I don't understand what do you want to say here. The glvalue result (of |
No. The call f(i) results in a glvalue (which is discarded) that refers to the object designated by "i". |
Ok, IIUC we agree that the result of |
The result of |
[expr.call] says: «The result of a function call is the result of the possibly-converted operand of the
I'm not avoiding it:
|
You're removing "return statement" from the list of copy-initialization contexts, it seems. |
Because it doesn't really perform a copy-initialization. It uses imaginary variable copy-initialization just to determine the sequence of conversions to be applied to the operand. Maybe I should reword [stmt.return] to say that it initializes an imaginary variable by the initializer of the form |
Saying that a hypothetical variable is copy-initialized sounds reasonable; I'm not sure we need to spell out the explicit syntax. However, if we say that, "return" should certainly stay in the list for copy-initialization in [dcl.init]. Before we dig any deeper, I'm increasingly getting the impression we're leaving "editorial issue" grounds here. |
I understand, the change of the «the \tcode{return} statement initializes the ... prvalue result object» wording could raise doubts if programs have the same meaning under the new wording. |
BTW, do we need to parenthesize the operand? |
We can't even parenthesize it, because if the operand is braced-init-list, the parenthesized operand can't be used as a variable initializer :( |
So, after thinking for a little bit more: both [stmt.return] and [expr.call] need fix. More complex than which I've proposed here.
looks OK, but the current [expr.call] wording:
looks defective. The operand can be a braced-init-list which is not a (prvalue) expression, so it doesn't have a result. Functions with reference return types will have to be handled differently, probably in a way similar to how it was proposed at the end of #3124 (comment) |
Agree! I think the wording "glvalue result" is so unclear in [stmt.return] p2 sentence 4, what actually the wording intents to refer to? Maybe the proposal in that link should be changed to :
I think It will be more better. My reason is , It will also cover this case: int& f(int& ref) { return ref; #1 }
int main()
{
int i = 0; #2
int v = f(i); // ok , `f(i)` is a glvalue of type int, which refers to `i`. and v is copy-initialized by the result from after applying l-to-r conversion to `i`.
} That is said, the entity which will be initialized by |
The suggested changes do not seem like an improvement to me. They do not make anything more clear. Quite the opposite. [stmt.return] defines what happens. [expr.call] is just referring to that definition not redefining it or contradicting it. Arguably the language in [expr.call] is a bit informal, but I don't see any circularity. I read the "is the result of the possibly-converted operand" in [expr.call] to mean the same thing as [stmt.return], namely that the result is copy-initialized from the operand, which might require a conversion. |
However, I think the wording "glvalue result" in [stmt.return] is unclear. where is the definition for such a wording in the standard document? So for example, int& func(int& ref){
return ref;
}
int main(){
int a = 0;
int& v = func(a);
} The function call expression, namely
Consider the below rule which is said in [stmt.return] section
IIUC, for my example, presumably, what the actually intent of this sentence is saying that, the reference But I have to say that in the declaration |
The result of the function is just the expression |
The aim to make "anything more clear" of the suggested changes is not. The aim is to correctly formalize the guaranteed copy elision. Formalized wording often looks less "clear" than colloquial description. Ofc everyone "knows" that T f() { return e; }
T v = f(); is "equivalent" to
As it was discussed above, in some cases this means that the [object, denoted by the] operand is copy-initialized from itself, when it has already been initialized somewhere else. This is nonsense.
https://timsong-cpp.github.io/cppwp/n4659/basic.lval#def:result,glvalue |
Yes, that's the relevant quote. However, consider such a statement |
The result of a glvalue can be an object or function. Not an expression.
The result is [the object denoted by] |
So, that is said , the "glvalue result" which is |
Editorial meeting: "copy-initialization" is not good, talk about "full-expression is sequenced before". |
|
@jensmaurer: To be clear, the present patch does not (yet) reflect the editorial consensus, right? |
Right. |
It appears to me that, the following wording would more consistent with the behavior of the major implementations.
After this rewording, stmt.return#5 can still be consistent in either case. The |
I think I don't want to see anonymous references back. |
Why would be that? For declaration
I just say that |
I meant And the main difficulty here is how to describe function call prvalue result in case |
I think it is not necessary to change the wording about copy-initialization for prvalue result object, it works well, it remains
It's sufficient well. no matter what the operand is(expression or braced-init-list). I think that we just pay attention to the wording for the case of the glvalue result. I think we just amend the wording that I said by adding the special case |
@languagelawyer Since you mention the special case |
Well. It's good wording. I think we can use the same manner for the special case
|
Please reopen if you would like to continue with this. |
This is a follow up on #3124/#3587 @sdkrystian @jensmaurer .
This is by no means complete, lotsa wording after the changes and till the end of the subclause seems very broken, namely:
There is no "returned object" in
A f() { return A(); }
. The normative part and the Example should be reworded.\pnum The copy-initialization of the result of the call is sequenced before the...
We don't have a copy-initialization of the result, so this should also be reworded.