You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[lib] LWG 3239: inline definition in the header / class synopsis #3110
Beyond the accepted =default and =delete, actual code definitions (with braces) have crept up in the header or class synopses with the recent batch of motions. The alternative presentation would be to have an itemdecl / itemdescr with "Effects: Equivalent to" codeblock.
For example, this applies to constructors and inline friends.
We should clarify the style guidelines to say what we want here.
For hidden friends this is intentional, to show that they are supposed to be defined inline and not have a namespace-scope declaration. Simply defining them inline isn't sufficient for that though (nothing prevents an implementation from adding a declaration outside the class), so there's a proposal to define new wording that states the intent clearly.
For member functions there's a sort-of-policy to define then inline if they use return type deduction, which is @AlisdairM's idea and is proving unpopular.
I'm mostly ok (although not enthusiastic) regarding the rule for the delegating constructors, but the hidden friends are not helpful as-is. We should rather have blanket wording that all friends shown in a class synopsis shall not have namespace-level declarations (unless expressly shown otherwise), which automatically implies that the friend declaration must also be the definition (but that's an implementation detail).
A namespace-scope redeclaration would make this requirement hard to meet:
In addition, the following sentence should become part of the entity’s specification via an
accompanying Remarks: element: “This function is to be found via argument-dependent
lookup only.”4
That suggests that every hidden friend does need a separate \itemdecl where the Remarks: element will appear, as the footnote says:
4 [One] might envision that a future draft of the C++ standard would include blanket library wording that may make such per-function specification unnecessary. Until then, we recommend that each befriended function be accompanied by the above-recommended wording restricting successful lookup of befriended functions to ADL only.
Or we could just add that blanket wording now, saying that all friend functions defined inline in the class synopsis are to be found via ADL only (maybe with a note saying that means no namespace-scope declaration). That would be a much smaller edit and would fix all existing uses of the idiom.
Specify in the library front matter that friend functions defined in the class definition are found via ADL only.
As a library editorial policy, use { \seebelow } in the class synopsis if the definition of the friend function gets large.
To be decided: Do we want to treat all inline friends like that, so that we have all/most of the description of library functions with \itemdecl / \itemdescr instead of having non-trivial code in the class synopsis.
Specify in the library front matter that friend functions defined in the class definition are found via ADL only.
Is there any reason to restrict this to only those friend functions that are defined in the class definition, as opposed to all friend functions declared in a class definition and not redeclared outside that class definition at namespace scope? To my knowledge we have no non-hidden friends declared in the Library since we largely leave it unspecified how non-member functions obtain access to class members needed to achieve their specification. Conversely, we have seen a couple examples of functions that couldn't be inlined into a class definition due to the need to specify some non-code behavior; it would be a shame if we eventually stumble across such a function that we'd like to be a hidden friend.
EDIT: Bah, the second bullet above addresses my problem scenario. Let's ignore that bit of rationale, and revert my statement to "it would be nice to keep the location of function specification (inline in the class definition vs. \itemdecl / \itemdescr) orthogonal to that function's hidden-friendliness and/or deduced return type-ness unless there's a specific reason to constrain ourselves to only friend functions defined directly in class definitions.
changed the title [-][lib] inline definition in the header / class synopsis[/-][+][lib] LWG 3239: inline definition in the header / class synopsis[/+]on Aug 5, 2019
@CaseyCarter, I agree. In general, we should keep the amount of inline code to a minimum, and favor \itemdecl / \itemdescr instead. However, the \itemdecl itself might be construed as an out-of-line declaration, with the resulting detrimental effect on an intended "ADL-only" function. So, we need clear front-matter wording that any friend function shown in a class synopsis is of the "ADL-only" variety.
Activity
jwakely commentedon Jul 31, 2019
For hidden friends this is intentional, to show that they are supposed to be defined inline and not have a namespace-scope declaration. Simply defining them inline isn't sufficient for that though (nothing prevents an implementation from adding a declaration outside the class), so there's a proposal to define new wording that states the intent clearly.
For member functions there's a sort-of-policy to define then inline if they use return type deduction, which is @AlisdairM's idea and is proving unpopular.
jwakely commentedon Jul 31, 2019
For constructors we've been defining them inline for some time, when the constructor delegates to another and has an empty body.
jensmaurer commentedon Jul 31, 2019
I've started a description here:
https://github.com/cplusplus/draft/wiki/Specification-Style-Guidelines#inline-definitions-in-synopses
I'm mostly ok (although not enthusiastic) regarding the rule for the delegating constructors, but the hidden friends are not helpful as-is. We should rather have blanket wording that all friends shown in a class synopsis shall not have namespace-level declarations (unless expressly shown otherwise), which automatically implies that the friend declaration must also be the definition (but that's an implementation detail).
jwakely commentedon Jul 31, 2019
That's what http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1601r0.pdf aims to fix.
jensmaurer commentedon Jul 31, 2019
Except it doesn't add wording that prevents an implementation from adding a namespace-scope redeclaration.
jwakely commentedon Jul 31, 2019
A namespace-scope redeclaration would make this requirement hard to meet:
That suggests that every hidden friend does need a separate
\itemdeclwhere the Remarks: element will appear, as the footnote says:jwakely commentedon Jul 31, 2019
Or we could just add that blanket wording now, saying that all friend functions defined inline in the class synopsis are to be found via ADL only (maybe with a note saying that means no namespace-scope declaration). That would be a much smaller edit and would fix all existing uses of the idiom.
jensmaurer commentedon Aug 5, 2019
So, the result seems to be:
{ \seebelow }in the class synopsis if the definition of the friend function gets large.\itemdecl/\itemdescrinstead of having non-trivial code in the class synopsis.CaseyCarter commentedon Aug 5, 2019
Is there any reason to restrict this to only those friend functions that are defined in the class definition, as opposed to all friend functions declared in a class definition and not redeclared outside that class definition at namespace scope? To my knowledge we have no non-hidden friends declared in the Library since we largely leave it unspecified how non-member functions obtain access to class members needed to achieve their specification. Conversely, we have seen a couple examples of functions that couldn't be inlined into a class definition due to the need to specify some non-code behavior; it would be a shame if we eventually stumble across such a function that we'd like to be a hidden friend.
EDIT: Bah, the second bullet above addresses my problem scenario. Let's ignore that bit of rationale, and revert my statement to "it would be nice to keep the location of function specification (inline in the class definition vs.
\itemdecl/\itemdescr) orthogonal to that function's hidden-friendliness and/or deduced return type-ness unless there's a specific reason to constrain ourselves to only friend functions defined directly in class definitions.[-][lib] inline definition in the header / class synopsis[/-][+][lib] LWG 3239: inline definition in the header / class synopsis[/+]jensmaurer commentedon Aug 5, 2019
@CaseyCarter, I agree. In general, we should keep the amount of inline code to a minimum, and favor
\itemdecl/\itemdescrinstead. However, the\itemdeclitself might be construed as an out-of-line declaration, with the resulting detrimental effect on an intended "ADL-only" function. So, we need clear front-matter wording that any friend function shown in a class synopsis is of the "ADL-only" variety.This needs LWG coordination via LWG issue 3239.
jwakely commentedon Aug 6, 2019
Right. Technically, only a namespace-scope declaration in a synopsis codeblock counts as such, but we should avoid that subtlety.
jensmaurer commentedon Sep 30, 2019
Editorial teleconference: Let's wait until the LWG issue is resolved.
jensmaurer commentedon Dec 28, 2019
P1965R0 got merged, and with the updated editorial guidance, this seems to be moot.