cplusplus / CWG

Core Working Group
23 stars 7 forks source link

[expr.call] should cover the type of a function call to constructor #443

Closed xmh0511 closed 9 months ago

xmh0511 commented 9 months ago

Full name of submitter (unless configured in github; will be published with the issue): Jim X

[stmt.return.note] p1 says

[Note 1: A constructor or destructor does not have a return type. — end note]

Then, in [expr.call] p4, we have a special specification to the type of the function call to a destructor

If the postfix-expression names a destructor or pseudo-destructor ([expr.prim.id.dtor]), the type of the function call expression is void;

Then, for other function calls, the type of the expression is specified by

otherwise, the type of the function call expression is the return type of the statically chosen function (i.e., ignoring the virtual keyword), even if the type of the function actually called is different.

However, in [dcl.init.general] p16.6.3, we instead says

if the function is a constructor, the call is a prvalue of the cv-unqualified version of the destination type whose result object is initialized by the constructor.

Suggested Resolution

This should be also an exception documented in [expr.call] p4, I think.

The type of a function call to a constructor of a class S is S. Otherwise ...

jensmaurer commented 9 months ago

You can't call a constructor using "regular" function call syntax (everything that syntactically looks like a function call is actually a conversion), thus [expr.call] is not the right spot to discuss the type of a "constructor call" expression.

frederick-vs-ja commented 9 months ago

It seems to me that we should amend [dcl.init.general] p16.6.3:

[...] ~The function selected is called with the initializer expression as its argument;~ If the selection function is a conversion function, the intermediate conversion result is a function call expression that invokes the function with the initializer expression as its argument; otherwise ~if the function is a constructor~, the ~call~ intermediate conversion result is a prvalue of the cv-unqualified version of the destination type whose result object is initialized by the constructor. The ~call~ intermediate conversion result is used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization.

t3nsor commented 9 months ago

You can't call a constructor using "regular" function call syntax (everything that syntactically looks like a function call is actually a conversion), thus [expr.call] is not the right spot to discuss the type of a "constructor call" expression.

But [expr.call] paragraphs 6, 7 (except for the first sentence), 9, 10, and 11 do apply to constructor calls.

jensmaurer commented 9 months ago

But [expr.call] paragraphs 6, 7 (except for the first sentence), 9, 10, and 11 do apply to constructor calls.

Right, [expr.call] is a weird mixture between "how is a function called (regardless of syntax used)" and "how does a function call expression work". Talking about a "type of a constructor call (expression)" is in the latter camp, and my response clarified that there aren't any "constructor call expressions" to start with.

I'm in favor of disentangling that, but suggestions should use a holistic approach (function calls, conversion function calls, constructor calls, destructor calls, allocation/deallocation function calls, and any other kind of function call that is performed without actually using function call syntax). And that's likely enough changes that it should be in a paper.