This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 117a. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2025-05-24


1883. Protected access to constructors in mem-initializers

Section: 11.8.5  [class.protected]     Status: review     Submitter: Daveed Vandevoorde     Date: 2014-02-26

According to 11.8.5 [class.protected] paragraph 1, except when forming a pointer to member,

All other accesses involve a (possibly implicit) object expression (7.6.1.5 [expr.ref]).

It is not clear that this is strictly true for the invocation of a base class constructor from a mem-initializer. A wording tweak may be advisable.

Proposed resolution (March, 2025):

Change in 11.8.5 [class.protected] paragraph 1 as follows and move the example to a separate numbered paragraph:

An additional access check beyond those described earlier in 11.8 [class.access] is applied when a non-static data member or non-static member function is a protected member of its naming class (11.8.3 [class.access.base]). [ Footnote: ... ] As described earlier, access to a protected member is granted because the reference occurs in a friend or direct member of some class C. If the access is to form a pointer to member (7.6.2.2 [expr.unary.op]), the nested-name-specifier shall denote C or a class derived from C. Otherwise, if the member is a constructor, either C shall be the naming class or the access shall be the constructor call for a base class subobject of C performed by a constructor of C as described in 11.9.3 [class.base.init]. All other accesses involve a (possibly implicit) object expression (7.6.1.5 [expr.ref]). In this case Unless the access is an implicit destructor call for a base class subobject by a destructor of C (11.4.7 [class.dtor]), the class of the object expression shall be C or a class derived from C.

[Example 1 :

  class B {
  protected:
    int i;
    static int j;
    B(int = 0);
    ~B();
  };
  class D1 : public B {
    D1() : B(1) {                 // OK
      B b(*this);                 // error: destructor of B is protected
    }
    ~D1() = default;              // OK
  };
... -- end example ]