[...] 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]
Full name of submitter: Brian Bi
Reference (section label): [dcl.fct.def.default]
Issue description: [dcl.fct.def.default]/5 states:
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: