[comp.lang.c++] Inheriting friend-ship

black@blake.u.washington.edu (Jim Black) (02/13/91)

Regarding "inheriting friendship", which is not supported by C++ today --

(a) The problem

As acknowledged in the ARM, not being able to inherit friendship can
be awkward.  For instance:

class Collection { // abstract class
    friend class Iterator; 
    // ..
};
class Iterator { // (works for all collections)
    friend class Collection;
    // ..
};

Different collections (Set etc) inherit from Collection, and each
would provide it's own way of initializing and stepping the Iterator.
That is why a Collection is a friend of Iterator ... but we *lose* this
friendship for all classes derived from Collection in C++ today.

On the other hand, Stroustrup notes the following problem if C++ allowed 
friends to be inherited (ARM section 11.4) :

class ReallySecure {
     friend class Trusted;
     // ..
};
class TrustedUser {
     // ..
};
class Spy : public TrustedUser
     // aha!
};

(b) Solutions? 

So the main question is, is there a way to resolve these two conflicting
purposes of "friend" (and is it worth the trouble)?

Here is one way that seems possible to me.  I'd appreciate comments about it, 
or alternate suggestions:

=> Could access specifiers "private" and "protected" be used to allow more 
   flexible access-rights for friendship?  

=> Specifically, could "protected friend class C" be used to grant friendship 
   to class C *and* classes derived from C?  

(This would be a language extension, of course.  It's my understanding, though,
 that these access keywords don't have meaning for friend declarations at 
 present.  If they do, this doesn't work...)

(Note the access specifier where class friendship is granted would apply to 
 the target/friend, not the class granting friendship:  you'd grant friendship
 and _also_ grant propogation-rights with regard to that friendship.)

In this sense, all friends in C++ today are "private" by default (access is
not inherited), and the "ReallySecure" example above would still not compile, 
as desired.  But the Iterator example above could now be coded:

class Iterator {
  protected friend class Collection; 
  // now Collection & all *Collection* subtypes are friends
  // ..
};

Is this feasible, brain-dead, or what?  

--
Jim Black  (black@blake.u.washington.edu)