Repository navigation
CWG3109 [class.protected] Update to cover splices #784
Description
Activity
- changed the title
[-][section.label] Update [class.protected] to cover splices[/-][+][class.protected] Update to cover splices[/+]on Oct 25, 2025 If the member is designated by a splice-expression, shouldn't we skip the additional check in [class.protected] entirely? That's effectively how it works with private members.
If the member is designated by a splice-expression, shouldn't we skip the additional check in [class.protected] entirely? That's effectively how it works with private members.
Yes, but we achieve that behavior by explicitly sanctioning the access in in [class.access.base]/5.3. I'm seeking to achieve the same here with:
that member shall either be designated with a splice-expression or [...]
What do you think? Does my suggested wording achieve that? Do you think there's a simpler way of expressing it?
You put the wording "that member shall either be designated with a splice-expression" in the part that talks about forming a pointer-to-member. It seems that the exemption should also apply to direct accesses (i.e. using
.). We can say something like this:An additional access check beyond those described earlier in [class.access] is applied when a non-static data member or non-static member function is a protected member of its
namingdesignating class ([class.access.base]) and is not designated by a splice-expression.Reacted by Daniel M. KatzThat direction works for me as well!
Revised suggestion:
An additional access check beyond those described earlier in [class.access] is applied when a non-static data member or non-static member function is a protected member of its
namingdesignating class ([class.access.base]) and is not designated by a splice-expression.98 As described earlier, access to a protected member is granted because the reference occurs in a friend or direct member of some classC. If the access is to form a pointer to member ([expr.unary.op]), the nested-name-specifier shalldenotedesignateCor a class derived fromC. All other potentially evaluated accesses involve a (possibly implicit) object expression ([expr.ref]). In this case, the class of the object expression shall beCor a class derived fromC.What's the addition of "potentially evaluated" doing? I think we want the special "protected" rules to apply even for unevaluated stuff.
I think the issue is that the current text fails to account for the fact that you can have something like
sizeof(Base::m). It doesn't fall under "if the access is to form a pointer to member" nor does it involve an object expression because the implicit transformation doesn't happen in this case.Reacted by Daniel M. Katz... and we don't, in fact, apply the extra check for unevaluated stuff; is that the gist?
- changed the title
[-][class.protected] Update to cover splices[/-][+]CWG3109 [class.protected] Update to cover splices[/+]on Nov 2, 2025 ... and we don't, in fact, apply the extra check for unevaluated stuff; is that the gist?
Yes. It seems that the way implementations behave is that for unevaluated cases, the additional check applies only if you have a class member access (taking into account the fact that one is not formed implicitly).
class A { protected: int m; }; class B : A { void f() { auto p = &A::m; // error auto s1 = sizeof(A::m); // ok auto s2 = sizeof(A().m); // error } };So we should say something like this: "Otherwise, if the access involves a (possibly implicit) object expression, [...]. [Note: Some unevaluated accesses do not fall under any of the rules in this paragraph and therefore, no additional check applies to them.]"
Full name of submitter: Dan Katz
Reference (section label): [class.protected]/1
Issue description
[class.protected] establishes the "additional rule" for access to non-static data members in the context of forming a pointer-to-member. Just as [class.access.base]/5.3 waives access rules for members designated through a splice-expression, this clause should do the same. As the rules currently stand, the following is well-formed when
mis a private member ofBase:but [class.protected]/1 implies that the same is ill-formed when
mis a protected member ofBase, since there is no nested-name-specifier that denotesDerivedor a class derived fromDerived. Furthermore, the phrase "naming class" is used, whereas P2996 replaced this term with "designating class". Lastly, because a nested-name-specifier can be a splice-expression (e.g.,&[:reflection_of_class:]::member), the verb "designates" should be preferred in lieu of "denotes".Worth noting: This paragraph fails to account for access that occur in unevaluated contexts, but addressing this seems to tread too closely to CWG2902 for comfort, so I'm leaving that as-is for now (but added a comment on the relevant issue).
Suggested resolution
Apply the following changes to [class.protected]/1:
Optionally, we could try to drive-by fix the "unevaluated context issue" by modifying the last two sentences as follows:
But if the interaction to CWG2902 is too close, then we can ignore it for now.