cplusplus / CWG

Core Working Group
23 stars 7 forks source link

CWG2809 [dcl.fct.def.default] Clarify that the implicitly generated definition does not redeclare the function #434

Closed t3nsor closed 5 months ago

t3nsor commented 1 year ago

Full name of submitter: Brian Bi

Reference (section label): [dcl.fct.def.default]

Issue description: [dcl.fct.def.default]/5 states:

[...] A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. A non-user-provided defaulted function (i.e., implicitly declared or explicitly defaulted in the class) that is not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) or needed for constant evaluation ([expr.const]).

In the first case (the function is user-provided), there is a second point of declaration for the function, wherever the user wrote the definition. The juxtaposition of these two sentences may give the impression that, in the second case (a non-user-provided defaulted function), there is also second point of declaration at the point where the function is odr-used or needed for constant evaluation. The only hint that this is not the case is the use of the word "when" rather than "where". This is very subtle and I think it should be called out in a note.

(The "second point of declaration" interpretation would cause a bizarre situation in which, in the case of a hidden friend comparison operator that is defaulted at its first declaration, after the first reference to that operator that causes it to be implicitly defined, it would no longer be a hidden friend. No compiler actually takes such an interpretation.)

Suggested resolution: Modify [dcl.fct.def.default]/5 as shown:

Explicitly-defaulted functions and implicitly-declared functions are collectively called defaulted functions, and the implementation shall provide implicit definitions for them ([class.ctor], [class.dtor], [class.copy.ctor], [class.copy.assign]) as described below, including possibly defining them as deleted. A defaulted prospective destructor ([class.dtor]) that is not a destructor is defined as deleted. A defaulted special member function that is neither a prospective destructor nor an eligible special member function ([special]) is defined as deleted. A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration. A user-provided explicitly-defaulted function (i.e., explicitly defaulted after its first declaration) is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly defined as deleted, the program is ill-formed. [Note 1: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note] A non-user-provided defaulted function (i.e., implicitly declared or explicitly defaulted in the class) that is not defined as deleted is implicitly defined when it is odr-used ([basic.def.odr]) or needed for constant evaluation ([expr.const]). ~[Note 1: Declaring a function as defaulted after its first declaration can provide efficient execution and concise definition while enabling a stable binary interface to an evolving code base. — end note]~ [Note 2: The implicit definition of a non-user-provided defaulted function does not reintroduce that function. — end note]

jensmaurer commented 11 months ago

CWG2809