Created on 2004-06-16.00:00:00 last changed 7 months ago
Proposed resolution (April, 2011)
Change 11.8.3 [class.access.base] paragraph 4 as follows:
A base class B of N is accessible at R, if
an invented public member of B would be a public member of N, or
R occurs in a member or friend of class N, and an invented public member of B would be a private or protected member of N, or
R occurs in a member or friend of a class P derived from N, and an invented public member of B would be a private
or(but not a protected [Footnote: A protected invented member is disallowed here for the same reason the additional check of 11.8.5 [class.protected] is applied to member access: it would allow casting a pointer to a derived class to a protected base class that might be a subobject of an object of a class that is different from the class context in which the reference occurs. —end footnote]) member of P, or
there exists a class S such that B is a base class of S accessible at R and S is a base class of N accessible at R.
[Example:
class B { public: int m; }; class S: private B { friend class N; }; class N: private S { void f() { B* p = this; // OK because class S satisfies the fourth condition // above: B is a base class of N accessible in f() because // B is an accessible base class of S and S is an accessible // base class of N. } }; class N2: protected B { }; class P2: public N2 { void f2(N2* n2p) { B* bp = n2p; // error: invented member would be protected and naming // class N2 not the same as or derived from the referencing // class P2 n2p->m = 0; // error (cf 11.8.5 [class.protected]) for the same reason } };—end example]
Notes from October 2004 meeting:
The CWG tentatively agreed that casting across protective inheritance should be subject to the additional restriction in 11.8.5 [class.protected].
Does the restriction in 11.8.5 [class.protected] apply to upcasts across protected inheritance, too? For instance,
    struct B {
        int i;
    };
    struct I: protected B { };
    struct D: I {
        void f(I* ip) {
            B* bp = ip;    // well-formed?
            bp->i = 5;     // aka "ip->i = 5;"
        }
    };
I think the rationale for the 11.8.5 [class.protected] restriction applies equally well here — you don't know whether ip points to a D object or not, so D::f can't be trusted to treat the protected B subobject consistently with the policies of its actual complete object type.
The current treatment of “accessible base class” in 11.8.3 [class.access.base] paragraph 4 clearly makes the conversion from I* to B* well-formed. I think that's wrong and needs to be fixed. The rationale for the accessibility of a base class is whether “an invented public member” of the base would be accessible at the point of reference, although we obscured that a bit in the reformulation; it seems to me that the invented member ought to be considered a non-static member for this purpose and thus subject to 11.8.5 [class.protected].
(See also issues 385 and 471.).| History | |||
|---|---|---|---|
| Date | User | Action | Args | 
| 2025-03-05 21:47:19 | admin | set | status: drafting -> open | 
| 2011-09-06 00:00:00 | admin | set | status: review -> drafting | 
| 2011-04-10 00:00:00 | admin | set | status: drafting -> review | 
| 2010-08-23 00:00:00 | admin | set | status: review -> drafting | 
| 2010-02-16 00:00:00 | admin | set | messages: + msg2549 | 
| 2010-02-16 00:00:00 | admin | set | status: drafting -> review | 
| 2005-10-22 00:00:00 | admin | set | status: open -> drafting | 
| 2004-11-07 00:00:00 | admin | set | messages: + msg1088 | 
| 2004-06-16 00:00:00 | admin | create | |