Re: Class templates and friend function templates
Hi Alex,
I appreciate your thoughts.
"Alex Blekhman" <tkfx.N05P4M@xxxxxxxxx> wrote in message
news:uNCnDtIkFHA.3448@xxxxxxxxxxxxxxxxxxxx
John Carson wrote:
It would appear in fact that, where friend declarations
are concerned, partial specialisation is ruled out for
*both* functions *and* classes. This is stated by
Vandevoorde and Josuttis (C++ Templates: The Complete
Guide, p. 117) and experimentation confirms it.
Unfortunately I don't have this book at hand. However, I
looked in the standard, paragraph 14.5.3/1. There are
several examples of template friends:
template<class T> class task;
template<class T> task<T>* preempt(task<T>*);
template<class T> class task {
// ...
friend void next_time();
friend void process(task<T>*);
friend task<T>* preempt<T>(task<T>*);
template<class C> friend int func(C);
friend class task<int>;
template<class P> friend class frd;
// ...
};
---
[...] each specialization of the `task' class template has
all specializations of the function template `func' as
friends.
---
I think it's the same case as our operator ==. It's enough
that friend's template arguments are different from class'
template arguments, so compiler is free to match any
friend's specialization then.
I don't have any problem with that. What is curious is that in
template <class T>
class C
{
public:
C(int x_) : x(x_) {}
private:
int x;
template <class Other>
friend bool operator == (C<T>&, C<Other>&);
};
operator== does not have two template parameters distinct from the template
parameter of the enclosing class. It only has one parameter that is
distinct, thus implying a kind of partial specialisation of the friend
declaration once C is instantiated for a particular type. If this simply
didn't compile, then the mystery would disappear. Seemingly, what is
happening is that the T that appears in C<T>& in the operator's parameter
list is treated as distinct from the T that is the template parameter for
the class. But if that is the case, then you would expect that the compiler
would require:
template <class T, class Other>
friend bool operator == (C<T>&, C<Other>&);
In addition, paragraph 14.5.3/4 states:
---
A template friend declaration specifies that all
specializations of that template, whether they are
implicitly instantiated (14.7.1), partially specialized
(14.5.4) or explicitly specialized (14.7.3), are friends of
the class containing the template friend declaration.
---
So, given all that, the specialization (from original post)
bool operator == (C<int>&, C<float>&);
is a friend both of C<int> and C<float>. That answers the
question why it has an access to both instantiations if
C<T>.
What is a little curious to me is that compilers will
accept a friend declaration for a function that has the
appearance of allowing a partial specialisation of the
friend declaration, when in fact the friend declaration
is not specialised at all. When I try to do something
analogous with a class, it won't compile, e.g.,
#include <iostream>
using namespace std;
template<class X, class Y>
class B;
template<class T>
class A
{
template<class Other>
friend class B; //won't compile
int x;
public:
A(int x_) : x(x_)
{}
};
Actually, there is a missing template argument for B.
I know there is, but it was also missing in the operator== friend
declaration and that still compiled. See above.
When you specify it, then code compiles without problems:
//...
template<class Other, class Whatever>
friend class B;
There can be T instead of Other or Whatever arguments.
VC++ lets you use T, but Comeau won't let you re-use the template parameter
from the enclosing class. Comeau's behaviour makes more sense since it makes
it clear that the friendship rights do not require that classes A and
B share a template argument.
--
John Carson
.
Relevant Pages
- Re: Class templates and friend function templates
... > It never occurred to me that the friend declaration could be an overload. ... > template ... I suspect the online version uses an EDG option to "instantiate ... (microsoft.public.vc.language) - Re: does not compile with "using namespace std"
... That means that a specialisation of class Stack for some ... template parameter T will have the following function ... because you haven't provided a definition for the friend operator <<. ... (comp.lang.cpp) - Re: Class templates and friend function templates
... >> Function template doesn't support partial specialization. ... > issue is the specialisation of the *friend declaration*, ... > appearance of allowing a partial specialisation of the ... (microsoft.public.vc.language) - Re: Class templates and friend function templates
... That certainly helps make sense of why the code compiles. ... If the friend declaration declares an overload, ... As for Comeau, I have used the online version for a long time as a test of correctness, but clearly I need the full version if I am to test some of the subtler template issues. ... (microsoft.public.vc.language) - Re: Class templates and friend function templates
... template instantiation is similar to class template instantiation. ... Function template doesn't support partial specialization. ... The issue is the specialisation of the *friend declaration*, not the specialisation of the operator. ... (microsoft.public.vc.language) |
|