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

The operand in the copy-initialization of the result object of a function should be the possibly-converted one #4847

Closed
xmh0511 opened this issue Aug 30, 2021 · 7 comments

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Aug 30, 2021

[stmt.return] p2 says

the return statement initializes the glvalue result or prvalue result object of the (explicit or implicit) function call by copy-initialization from the operand.

where the operand is defined as

The expr-or-braced-init-list of a return statement is called its operand.

Instead, [expr.call] p9 says

The result of a function call is the result of the possibly-converted operand of the return statement ([stmt.return]) that transferred control out of the called function (if any)

It seems to be a bit inconsistent. It is not clear whether the return statement uses the possible-converted operand to copy-initialize the result object or just the original operand. The concern comes from the following example

struct B{
  B(int){}
};
struct A{
  operator B(){
     return 0;
  }
};
A a;
B const& rf = a;  //#1

According to [dcl.init.ref#5.4.1], the initializer expression at #1 should be first converted to type B with a user-defined conversion, which is B::operator B, and [dcl.init.ref#5.4.1] also says

The result of the call to the conversion function, as described for the non-reference copy-initialization, is then used to direct-initialize the reference. For this direct-initialization, user-defined conversions are not considered.

For the direct-initialization of the reference, temporary materialization conversion will be applied to the conversion function call, which means the temporary object is used as the result object that is copy-initialization from the operand of the return statement, as aforementioned. At this point, according to [dcl.init#general-15.6.3], it will invoke user-defined conversions to transform the operand (0) to the destination type to initialize the result object(temporary object ). However, as [dcl.init.ref#5.4.1] said, user-defined conversions are not considered.

I think the wording about the return statement may be that

the return statement initializes the prvalue result object of the (explicit or implicit) function call by copy-initialization from the possibly-converted operand that is implicitly converted to the return type(if any).

@jensmaurer
Copy link
Member

No, copy-initialization subsumes the conversion.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 31, 2021

Do you mean the copy-initialization that occurred in the return statement subsumes the conversion of 0 to type A? If it is, the direct initialization of the reference will comprise the user-defined conversion that occurs in the temporary materialization conversion, specifically, the user-defined conversion occurs in the return statement where the operand is used to initialize the result object. IMHO, it contradicts with that

For this direct-initialization, user-defined conversions are not considered.

To make this thought more clear, the B const& rf = a; is equivalent to

B const& rf(a.operator B());
// where the materialization conversion is equivalent to
B temporary_object = a.operator B();
// where the return statement in `A::operator B` has the effect, which is like
B temporary_object = 0;
// In the above copy-initialization, user-defined conversion(B::B(int)) is considered
// which is considered in direct-initialization of the reference rf

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 31, 2021

@jensmaurer Is any thought here?

@jensmaurer
Copy link
Member

I'm not seeing a problem. We copy-initialize the temporary (conversion function is fine). This completes the evaluation of the conversion function and any talk about operands of "return". As a distinct step, we then direct-initialize the reference with the temporary (no conversion functions involved).

@xmh0511
Copy link
Contributor Author

xmh0511 commented Aug 31, 2021

The temporary direct-initialize the reference is not specifying by [dcl.init.ref#5.4.1]. It just say

The result of the call to the conversion function, as described for the non-reference copy-initialization, is then used to direct-initialize the reference.

Where the call to the conversion function is a prvalue, bind it to a reference will trigger the materialization, which means a temporary object will copy-initialized from the operand, which requires the user-defined conversion, Occurs in direct-initializ the reference from a prvalue.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Sep 1, 2021

The relevant wording in C++11 standard was saying that the reference is bound to the temporary

Otherwise, a temporary of type “ cv1 T1” is created and initialized from the initializer expression using the rules for a non-reference copy-initialization ([dcl.init]). The reference is then bound to the temporary.

However, the concern in CWG1571, make the wording be changed, which claims that the conversion function call is direct-initialized the reference. In my example, this rule means we should continue to fall into [dcl.init.ref] p5 for it. What I'm concerning here is what's the extent of the application of the restriction that the user-defined conversions are not considered in this direct-initialization. Since we fall into [dcl.init.ref#5.3] for this direct-initialization, materialization conversion would apply to the conversion function call(prvalue), as discussed in the above comment, the copy-initialization of the temporary object does consider the user-defined conversion.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Nov 30, 2022

Maybe clarified by cplusplus/CWG#186

@xmh0511 xmh0511 closed this as completed Nov 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants