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
[expr.call] The result type of a function call and the value category relying on it #5415
Comments
It seems a bit clearer to use return type instead of result type after excluding (pseudo-)destructor calls (although they are not always the same, the difference doesn't matter here). (Pseudo-)destructor calls are already specified to have type |
Yes, It was my original thought before proposing the suggestion. However, it still does not clarify the result of the function call, as pointed out in this issue, we lack to specify the destination type of the conversion. So, instead of replacing You reminded me that we should have a special rule to specify the result/value category of the function call whose return type is |
Change [expr.call] p9 to
|
I don't think this is correct. For example,
I think this qualifies as "no conversion is required". The operand of the return statement is an lvalue, yet the function call |
Why wouldn't an lvalue-to-rvalue conversion apply to the operand
Since the function call
I think the proposed suggestion is not good for class type, consider this example struct B{};
B fun1(B& b){
return b;
} We have said that converting an argument of a class type to the same type is an identity conversion, which means no conversion is required. So, I think the proposed suggestion might be simplified to
Without considering what the original operand is. I think the declaration modeling a copy-initialization is consistent with [dcl.init.general] p14. With this suggestion, I think we should remove the last sentence in [stmt.return] p2, or change it to a note
Because, when a function call is a prvalue, it is not limited to being used to initialize an object, such as to be an operand of the operations(i.e. computes the value), that is, there is no result object to be initialized. And what is said in this sentence is covered by the suggestions. Also, it could clarify #4107 |
The wording should be clear that the type and value category of a function call only depend on the return type written in the function declaration. I think it would be helpful to separate that from the determination of the result (i.e. the value that is returned). I'm wondering whether we could simply say that the operand of the evaluated |
As I said above, the function call is not necessarily used to initialize something. Consider this snippet fun() + 1; There is no stuff to be initialized(especially, no result object), we just need to read the value for computation. So, the current rule for the Indeed that using "return type" to directly determine the value category of a function call is clearer. Nonetheless, The result of a function call is also needed to be clarified.
Yes, I also think so. However, IMO, to determine the result of a call, we should first determine what the value category is(e.g. a For the |
The example in #4847 actually wants to say we should consider any conversions required to match the operand of the return statement to the return type as part of the initialization of the invented declaration, in order to avoid the ambiguity when we say certain conversions are not considered when initializing the actual result object. With the help of the suggestion, it is easy to interpret the example in #4847 and the corresponding referenced rule will be well. struct B{
B(int){}
};
struct A{
operator B(){
return 0;
}
};
A a;
B const& rf = a; //#1 the function call to B t = 0;
B const& rf(t); The direct-initialization obeys [dcl.init.ref] p5.3, no user-defined conversion is required in this initialization. |
The issue in #4723 might be fixed by:
From a certain perspective, I think the returned reference is the invented variable that is of reference type. result object case: https://godbolt.org/z/orTWM5Gf7 returned reference case: https://godbolt.org/z/3zq3f5hcd |
What the result of a function call is may be clarified by cplusplus/CWG#186, and therefore what the type of the result is. Or, we may just need to use the return type in the rule. |
[expr.call] p14 says
So, the type of the result of a function call is significant to determine the value category of the function call. However, it's unclear the type of the result in a normal function call. [expr.call] p9 just says
It does specify the destination type for the case that the return types of the final overrider and the statically chosen function are different. However, for the conversion in the first step, it is vague to the destination type of the conversion(if any).
When we build up a conversion, we usually use the utterance: convert the expression
E
to typeT
. For the above case, we lack to specify the destination typeT
(in the first conversion). The improvement might be:Moreover, [conv.general] p6 defines what the result of a conversion is.
The modified rule together with [conv.general] p6 are clear to clarify the value category that relies on the result type of the function call.
The result of the conversion is defined as
A t = 0;
The result of the call (
t
) is a prvalue of classA
, thus the function call is a prvalue.The text was updated successfully, but these errors were encountered: