Topic: friendship and member function templates of class templates


Author: Jean-Marc Bourguet <jm@bourguet.org>
Date: Sat, 26 Feb 2011 11:24:38 CST
Raw View

See the following code:

template <typename T> struct Foo {
   template <typename U> void f(U const&);
};

struct Bar
{
   // this is possible
   friend void Foo<Bar>::f<Bar>(Bar const&);

   // the following isn't AFAIK (the first two were what triggered my
   // investigation, the later are two just for completeness)
   template <typename T> friend void Foo<Bar>::f<T>(T const&);
   template <typename T> friend void Foo<T>::f<Bar>(Bar const&);
   template <typename T> friend void Foo<T>::f<T>(T const&);
   template <typename T> template <typename U> void Foo<T>::f<U>(U const&);
};

template <typename T>
struct Qux
{
   template <typename U> void f(U const&);

   // none seems possible
   friend void Qux<Qux>::f<Qux>(Qux const&);
   template <typename U> friend void Qux<Qux>::f<U>(U const&);
   template <typename U> friend void Qux<U>::f<Qux>(Qux const&);
   template <typename U> friend void Qux<U>::f<U>(U const&);
   template <typename U> template <typename V> void Qux<U>::f<V>(V const&);
};

Compilers I've tried were giving more or less cryptic error messages, none
which helped me to find out a better syntax and some apparently completely
unrelated (type    Qux<Qux<T> >    is not derived from type    Qux<T>    for
instance).

Looking in the standard, I found nothing remotely relevant excepted
14.5.3/6 which starts by "A member of a class template may be declared
friend of a non-template class..." which could imply that a member of a
class template may not be declared friend of a template class (thus
explaining the Qux case as just a bad QOI of the compilers).  But I've
found nothing for the Foo/Bar one.

--
Jean-Marc


[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub.johannes@googlemail.com>
Date: Sat, 26 Feb 2011 13:31:28 CST
Raw View
Jean-Marc Bourguet wrote:

>
>
> See the following code:
>
> template <typename T> struct Foo {
>    template <typename U> void f(U const&);
> };
>
> struct Bar
> {
>    // this is possible
>    friend void Foo<Bar>::f<Bar>(Bar const&);
>
>    // the following isn't AFAIK (the first two were what triggered my
>    // investigation, the later are two just for completeness)
>    template <typename T> friend void Foo<Bar>::f<T>(T const&);
>    template <typename T> friend void Foo<T>::f<Bar>(Bar const&);
>    template <typename T> friend void Foo<T>::f<T>(T const&);
>    template <typename T> template <typename U> void Foo<T>::f<U>(U
>    const&);
> };

I personally can't really find much sense in 14.5.4 the way it's worded.
What seems to be its intent:

- Paragraph 1 covers all the declarations that aren't the declaration of a
template-declaration.
- Paragraph 2 covers all non-member template declarations (I think that this
is its intent, since it goes on to say you can define a friend function
template, which is certainly not true of member template friends, and
because Paragraph 5 describes member templates of class templates. Curiously
though, Clang allows to define member templates of other classes. Maybe it's
another victim of this confusing wording).
- Paragraph 3 describes behavior for template friend declarations (including
member templates?). It does not explicitly allow friend declarations for
non-template class members, though.
- Paragraph 5 covers friend declarations for class template members
(including member templates). It does not seem to cover "Foo<Bar>::f", since
"Foo<Bar>" is not a class template but a specialization of it. It also
misuses the term "signature", I believe.

In any case, your first case is not covered explicitly anywhere, it seems.
But comparable cases are valid in several implementations, so I think you
need the following syntax

   template<typename T> friend void Foo<Bar>::f(T const&);

This is a function template declaration, and therefor shall not use a
template-id (which is only valid for partial specialization, if you declare
a template).

Paragraph 5 allows declaring class template members as friend of a non-
template class, which is just what you are doing as the second case (the
specialization of a member function template). I'm guessing that the spec
does not support this. For the third case, I again think that the spec does
not support this.

For the last case, you make the member template of the template "Foo<T>" a
friend (paragraph 5). Just omit the "<T>", like

   template <typename T> template <typename U> void Foo<T>::f(U const&);

OMG, now I'm getting a headache!

>
> template <typename T>
> struct Qux
> {
>    template <typename U> void f(U const&);
>
>    // none seems possible
>    friend void Qux<Qux>::f<Qux>(Qux const&);
>    template <typename U> friend void Qux<Qux>::f<U>(U const&);
>    template <typename U> friend void Qux<U>::f<Qux>(Qux const&);
>    template <typename U> friend void Qux<U>::f<U>(U const&);
>    template <typename U> template <typename V> void Qux<U>::f<V>(V
>    const&);
> };
>
> Compilers I've tried were giving more or less cryptic error messages, none
> which helped me to find out a better syntax and some apparently completely
> unrelated (type    Qux<Qux<T> >    is not derived from type    Qux<T>    for
> instance).
>
> Looking in the standard, I found nothing remotely relevant excepted
> 14.5.3/6 which starts by "A member of a class template may be declared
> friend of a non-template class..." which could imply that a member of a
> class template may not be declared friend of a template class (thus
> explaining the Qux case as just a bad QOI of the compilers).  But I've
> found nothing for the Foo/Bar one.
>

It looks like its intent is to only allow members of class templates friends
if the friend declaration is in a non-template class.


--
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]