Topic: Can't a template class be a friend to itself ?


Author: Jason.Chen@efi.com
Date: 2000/08/03
Raw View
Hi,
     I encountered a problem with friend declaration while implementing
a STL-like list class.  When I compile the same code under VC++, SGI CC
and g++, I got different results.  Specifically, VC++ and SGI CC allows
a friend class declaration to itself, but g++ doesn't seem to like it.
Please see the following code:

template<class T> class list; // forward declaration

template<class T, class Ref, class Ptr> class _list_iterator {
public:
    typedef _list_iterator<T, T&, T*> iterator;
    typedef _list_iterator<T, const T&, const T*> const_iterator;

    friend class list<T>;  // so it can use the private constructor
    friend class _list_iterator<T, const T&, const T*>;
       // so const_iterator's constructor can access iterator's private
       // field.

private:
    _list_node_base *cursor;
    _list_iterator(_list_node_base *p) : cursor(p) {}
public:
    _list_iterator() : cursor(NULL) {}
    //  allow conversion from iterator to const_iterator
    _list_iterator(const iterator& iter) : cursor(iter.cursor) {}
    .......
};

template<class T> class list {
    .....
private:
    node root;
public:
    typedef _list_iterator<T, T&, T*> iterator;
    typedef _list_iterator<T, const T&, const T*> const_iterator;

    iterator begin() { return iterator(root.next); }
    const_iterator begin() const { return const_iterator(root.next); }
    ......
};

     This code tries to hide the details of _list_iterator therefore
two friend declarations are used to grant accesses:
(1) For list<T> to construct iterator or const_iterator
(2) For a const_iterator to access iterator's private field, thus
    making it possible to convert an iterator to const_iterator.

     Now the problem happens with this friend declaration in the
_list_iterator template:
         friend class _list_iterator<T, const T&, const T*>;

     While instantiating _list_iterator<T, const T&, const T*> (by
list<T>::const_iterator), this declaration is essentially trying
to make friends with itself.  The result I got was:

   VC++ 6.0   : code compiles without error or warning
   SGI CC 7.30: code compiles with warning saying pointless friend
                declaration while instantiating
                _list_iterator<int, const int&, const int*>
   g++  2.95  : code won't compile.  the error was implicit friend
                declaration with itself

     So I did a little test, trying to instantiate obj<int> by the
following class template:

template<class T> obj {
    friend class obj<T>;    // same result as above, i.e. VC++/SGI CC
                            // works, g++ error
    friend class obj<int>;  // compiles on all three compilers.
                            // SGI CC 7.30 gave the same warning as
                            // above
private:
    T obj;
    ....
};

     So it seems that it is okay to declare a friend class to itself
as long as the declaration doesn't involve the template argument.  But
I am confused if g++'s behavior is correct.  It seems to me that a
friend declaration to itself should be allowed, and in my case I needed
it to keep the details of _list_iterator class private.
     Any comments are appreciated.


// Jason Chen                     //
// Electronics For Imaging, Inc.  //
// E-MAIL: Jason.Chen@efi.com     //


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              ]