SC22/WG21/N1198
J16/99-0021
31 August, 1999
Thomas R Wilcox
trw@rational.com
Issues Relating to Accessibility
This document discusses problems with the specification of the concept of accessibility in the standard and proposes a possible resolution. The discussion is motivated by four items on the core issues list:
Issues 9 and 16: Clarification of Access to Base Class Members
-4- A base class B of class N is said to be accessible at a point of reference if an invented public member of the base class B is accessible when named in N. If a base class is accessible, one can implicitly convert a pointer to a derived class to a pointer to that base class (conv.ptr, conv.mem). [Note: it follows that members and friends of a class X can implicitly convert an X* to a pointer to a private or protected immediate base class of X. ] The access to a member is affected by the class in which the member is named. This naming class is the class in which the member name was looked up and found. [Note: this class can be explicit, e.g., when a qualified-id is used, or implicit, e.g., when a class member access operator (expr.ref) is used (including cases where an implicit ``this->'' is added. If both a class member access operator and a qualified-id are used to name the member (as in p->T::m), the class naming the member is the class named by the nested-name-specifier of the qualified-id (that is, T). If the member m is accessible when named in the naming class according to the rules below, the access to m is nonetheless ill-formed if the type of p cannot be implicitly converted to type T (for example, if T is an inaccessible base class of p's class). ] A member m is accessible when named in class N if
class B; class A { private: int i; friend void f(B*); }; class B : public A { }; void f(B* p) { p->i = 1; //OK: B* can be implicitly cast to A*, // and f has access to i in A }
--- end example]
------------------------------------------------------------
Discussion
of issues....Issue 9 Example: class D; class B { protected: int b1; friend void foo( D* pd ); }; class D : protected B { }; void foo( D* pd ) { if ( pd->b1 > 0 ); // Is 'b1' accessible? }
Analysis: Is b1 accessible in foo?
Issue 16 Example: class D; class B { private: int i; friend class D; }; class C : private B { }; class D : private C { void f() { B::i; //1: well-formed? i; //2: well-formed? } };
(A) Is B::I well-formed?
(B) Is i accessible in f when named in D?
So, in both these cases, friendship with the base class does not grant access to the private member because the base class is not accessible through two levels of private base classes. If, however, B were merely a protected base of C rather than a private base of C, then i would be accessible within f because B would be an accessible base of D within f (f is a member of D and a public member of B would be a private member of D) and it has already been established that i is accessible within f when named in B. The B:: qualification is redundant in this case.
Issue 19: Clarifying Protected Member Access
In the discussion of issue 19 in Dublin it was decided that 11.5 was fine as it stood without reference to the naming class concept of 11.2 since the additional requirement defined in 11.5 is orthogonal to the naming class. The naming class issues are already dealt with in clause 11.2, to which this clause already refers.
Issue 17: Footnote in 11.2 Should Discuss the Naming Class
The footnote in paragraph 1 of clause 11.2 currently reads
[Footnote: As specified previously in clause
It would appear that the sole intent of this footnote is to point out that the partitioning of members into public, protected, and private members in the first paragraph is not complete. And that indeed there are members of a class that are neither public, protected, or private. The issue is discussed more completely in SC22/WG21/N1179 J16/99-0002.
Although the wording of the footnote could be strengthened, it is correct as it stands and, therefore, should not be considered a defect. The use of friend clauses is necessary for access to private members outside the base class, although it may not be sufficient in some naming contexts when private inheritance is used for derived classes. In fact, these additional restrictions are the subject of the paragraphs that follow this footnote in the clause, and the footnote really can't say more.
For these reasons, I recommend that this issue not be considered a defect.