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 ]