Topic: Friendship and Partial Specialisation


Author: Gavin Collings <gcollings@sperry-sun.co.uk>
Date: 1999/12/07
Raw View
Background
----------

When defining templates specialised on implementation, it is useful to
be able to specify exactly which members of the set are friends of
which others.

It may be that it is inappropriate for one implementation to access the
internals of another, as the two types would otherwise be completely
unrelated.  Allowing access on the main type, though is desirable to
allow for handling implicit conversions - i.e. to express relationships
that parallel those of the fundamental type being represented.

Questions
---------

It is possible to specify these types of relationships for friend
functions and member functions as follows.

   template <typename T, typename I=implementation> class C
   {
   public:
      template <typename T1>
      member_sharing_impl( C<T1,I> c )
      {
         member = c.member;
      }

      template <typename T1, typename T2>
      friend void friend_sharing_impl( C<T1,I> c1, C<T2,I>& c2 )
      {
         c2.member = c1.member;
      }
   private:

      T member;
   };

My first question asks whether it is possible to express the
corresponding relationship between the classes.  What I want to write
is

   template <typename T, typename I=implementation> class C
   {
      ...
      template <typename T1> friend class C<T1,I>;
   };

but this syntax seems to be disallowed, is there an alternative?


My second is a little more involved, and specifically related to friend
functions.  Consider

   template <int I> class C
   {
   public:
      template <int J, int K>
      friend C<I> friend_func( C<J> c1, C<K> c2 )
      {
         C<I> result;
         result.member = c1.member + c2.member;
         return result;
      }

   public:  // Yes, public:, for now

      int member;
   };

This works. But try changing the second public to private and the
problem is apparent.  Substitute some trial indices you can see that:

   friend_func<1,2,3> is a friend of only C<1>

The equivalent declaration in, for example, C<2> is:

   friend friend_func<2,*,*>( C<*>, C<*> );

which does not include our friend(;) friend_func<1,2,3>.

What we really want is the ability to substitute the current class in
each of the parameter positions of friend_func - i.e. to write

   template <int I> class C
   {
   public:
      template <int J, int K>
      friend C<I> friend_func( C<J> c1, C<K> c2 );

      template <int J, int K>
      friend C<K> friend_func( C<I> c1, C<J> c2 );

      template <int J, int K>
      friend C<J> friend_func( C<K> c1, C<I> c2 );

   private:

      int member;
   };

The set of classes to which friend_func would then be a friend would be
the union of the above.

The work around is to allow friend_func into all of the C<>s instead of
just the ones in which it is interested.  I don't find that solution
very pleasing.

My compiler tells me that multiple friendship declarations are not
allowed.  To me this seems over-restrictive.  I can see the sense of it
in non-template programming where function declarations are unique and
unambiguous, but things just aren't like that with templates.  I
haven't thought this through to its conclusion, but would welcome any
insight into why this rule couldn't be relaxed.

--
Gavin Collings
gcollings@sperry-sun.co.uk


Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]