Topic: Specifying a templated class as a friend


Author: Kresimir Fresl <fresl@grad.hr>
Date: 1997/05/01
Raw View

Robert P. Krajewski wrote:

> I know that templates in C++ have been in flux for some time,
> and now it has bit me. Since this code is supposed to keep
> working, it's a nuts-and-bolts question. And I think it's a
> standards question since there seems to be a hole in the
> latest ANSI draft I've seen (December 1996).
...
> ... we have something like:
>
> template<class ct> class String {
>    ...
>    friend class WriteLock<ct>;   // friend declaration (and forward)
>    ...
> };
>
> template<class ct> class WriteLock {
>    ...
>    WriteLock(String<ct> & aString); // constructor
>    ...
> };


Class WriteLock<ct> should be `forward declared':

  template <class ct> class WriteLock; // <----

  template <class ct> class String {
  friend class WriteLock<ct>;
  public:
    String (ct c) : c_(c) { cout << "String: " << c_ << endl; }
  private:
    ct c_;
  };

  template <class ct> class WriteLock {
  public:
    WriteLock (String<ct> const& s) {
      cout << "WriteLock: " << s.c_ << "\n";
    }
  };

  main () {
    String<char> s1 ('c');
    WriteLock<char> w1 (s1);
  }

(Unfortunately, I do not know if this will work with
M$ VC++.)


> From what I was reading in the newest draft about templates,
> it doesn't look like what I want to do (specify a not-yet-defined
> templated class as a friend of templated class) is possible;

Class can be `not-yet-defined', but, as I said, it should be
`forward declared', that is, its name should be declared
before friend declaration.

> it only seems possible to specify templated functions
> as friends of non-templated classes. This is in section
> 14.5.3 (template.friend) of the December ANSI/ISO draft:
...
> And the syntax is odd, but I tried it:
>
>    template<ct> friend class WriteLock;
>
> ...and the Microsoft compiler spit back a different, cryptic
> error message at me.

It should be

  template <class ct> friend class WriteLock;
            ^^^^^

But, now

  // with or without
  template <class ct> class WriteLock;

  template <class ct> class String {
  template <class ct> friend class WriteLock;
    // as in previous example
  };

  // rest of the code as in previous example

Comeau C++ v4.0 gives a warning:

  ... warning: declaration of "ct" hides template parameter
    template <class ct> friend class WriteLock;
                    ^

This means that

  template <class ct> friend class WriteLock;
                  ^^

is the same as

  template <class ct1> friend class WriteLock;
                  ^^^

(which compiles without a warning), that is, with this
form of declaration template parameters in two classes are
unrelated (eg. WriteLock<char> can be friend of
String<wchar_t>).

> Am I misreading the spec ? Perhaps 14.5.3 only clarifies
> certain cases but doesn't preclude what I'm doing, or maybe
> it does.

AFAICS, it doesn't.

> But what makes me pessimistic is that it shows no example
> of a friend template class being declared using one of a
> defining classes' parameters.

Well, I think that there really is a lack of examples in
the Draft, particularly with templates. I had similar
problems (and some of them are still unresolved); for
more info you can read the thread `friend templates' in
comp.lang.c++.moderated. (In this thread you can find
Greg Comeau's explanation why in the second case there is
not need for `forward declaration' of WriteLock<ct>.)

K. Fresl
---
[ 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         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]