469,133 Members | 1,458 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,133 developers. It's quick & easy.

Confused about friends in template class

According to:
http://www.parashift.com/c++-faq-lit....html#faq-35.4
, if my understanding is correct, in

template<typename T>
class Foo {
friend void func (const Foo<T>& foo);
};

template<typename T>
void func (const Foo<T>& foo) { ... }

func is seen as a non-template function at class instantation time,
and the func function template is never actually instantieted, so the
linker error (the compiler is searching the ordinary one).

The proposed solution is via forward declaration, but (in VC 8) this
works:

template<typename T>
class Foo {

template<typename T>
friend void func (const Foo<T>& foo);
};

template<typename T>
void func (const Foo<T>& foo) { ... }
However gcc complains about the fact that T (of func) shadows T (of
Foo), but the following works:

template<typename T>
class Foo {

template<typename U>
friend void func (const Foo<U>& foo);
};

template<typename T// Or U, indifferent right?
friend void func (const Foo<T>& foo);

According to a book of mine (maybe outdated, 2002) it seems that the
difference between this last option and the one proposed in the guide
is that here func can be a friend of classes with different templates,
like:
func<Afriend of Foo<B>
while in the solution proposed in the guide this can not happend.

My intuition (probably wrong) is than that the "invalid VC syntax"
really means to the VC compiler the situation illustrated in the guide
via forward declaration, but this syntax is illegal according to the
standard.
Too bad, I liked this more concise solution :)

Anyway, if my understanding was correct, there are reasons to avoid
using always the last option, where the function is also a friend of
instantation of the class with different parameters?

Cheers
StephQ

May 16 '07 #1
4 1656
StephQ wrote:
According to:
http://www.parashift.com/c++-faq-lit....html#faq-35.4
, if my understanding is correct, in

template<typename T>
class Foo {
friend void func (const Foo<T>& foo);
};
You declared a non-template function func here...
>
template<typename T>
void func (const Foo<T>& foo) { ... }

func is seen as a non-template function at class instantation time,
and the func function template is never actually instantieted, so the
linker error (the compiler is searching the ordinary one).
And the compiler couldn't find a non-template function func to
instantiate Foo...What's confusing you?
>
The proposed solution is via forward declaration, but (in VC 8) this
works:

template<typename T>
class Foo {

template<typename T>
friend void func (const Foo<T>& foo);
};

template<typename T>
void func (const Foo<T>& foo) { ... }
However gcc complains about the fact that T (of func) shadows T (of
Foo), but the following works:

template<typename T>
class Foo {

template<typename U>
friend void func (const Foo<U>& foo);
};

template<typename T// Or U, indifferent right?
friend void func (const Foo<T>& foo);

According to a book of mine (maybe outdated, 2002) it seems that the
difference between this last option and the one proposed in the guide
is that here func can be a friend of classes with different templates,
like:
func<Afriend of Foo<B>
while in the solution proposed in the guide this can not happend.

My intuition (probably wrong) is than that the "invalid VC syntax"
really means to the VC compiler the situation illustrated in the guide
via forward declaration, but this syntax is illegal according to the
standard.
Too bad, I liked this more concise solution :)
It's concise but it's illogical and wrong, even though it may appear
convenient.
>
Anyway, if my understanding was correct, there are reasons to avoid
using always the last option, where the function is also a friend of
instantation of the class with different parameters?
I couldn't think of any reason to avoid using it.
>
Cheers
StephQ
May 16 '07 #2
And the compiler couldn't find a non-template function func to
instantiate Foo...What's confusing you?
Here i just wanted to check if I understood the explanation correctly.
It seemes this is the case :)
It's concise but it's illogical and wrong, even though it may appear
convenient.
Could expand the explanation a little more?
Is it wrong according to the standard? There is a particular reason
for that?
I couldn't think of any reason to avoid using it.
Perfect.

Thank you for you reply.

Cheers
StephQ

May 17 '07 #3
StephQ wrote:
>And the compiler couldn't find a non-template function func to
instantiate Foo...What's confusing you?

Here i just wanted to check if I understood the explanation correctly.
It seemes this is the case :)
>It's concise but it's illogical and wrong, even though it may appear
convenient.

Could expand the explanation a little more?
Is it wrong according to the standard? There is a particular reason
for that?
template<typename T>
class Foo {
public:
template<typename T>
friend void func (const Foo<T>& foo);
};

What's the point of declaring template <typename Tfor func? It gets
the template parameter by the function signature, i.e the argument. func
will be instantiated based on Foo's template paramter T. This is why you
are getting complaints from gcc. No need for standard to understand that
this is an dubious declaration. Once you remove the function template
declaration, you create a binding that for any instance of Foo<T>, there
must be a func<Tdefinition that completes it unless it's never used
anywhere (but that's not the point here).

It's an completely different story when you say:
template<typename T>
class Foo {
public:
template<typename U>
friend void func (const Foo<U>& foo);
};

Here you U and T are orthogonal and Foo<Tand func<Uare too. You
don't create any binding between these two definitions (sort of, when
you invoke func, its template argument type is determined by its
argument). This is a common way to get different template instantiations
to work together. Not in this particular example, but for this one:
template <typename T>
class Foo {
public:
template<typename U>
Foo<T>& func (const Foo<U>& foo);
};

Foo<intfi;
Foo<floatff;
ff.func(fi);

A common use is to write copy constructors this way to convert between
different template instantation of types.
>I couldn't think of any reason to avoid using it.

Perfect.

Thank you for you reply.

Cheers
StephQ
May 17 '07 #4
On May 17, 11:26 pm, Fei Liu <fei...@aepnetworks.comwrote:
StephQ wrote:
And the compiler couldn't find a non-template function func to
instantiate Foo...What's confusing you?
Here i just wanted to check if I understood the explanation correctly.
It seemes this is the case :)
It's concise but it's illogical and wrong, even though it may appear
convenient.
Could expand the explanation a little more?
Is it wrong according to the standard? There is a particular reason
for that?

template<typename T>
class Foo {
public:
template<typename T>
friend void func (const Foo<T>& foo);

};

What's the point of declaring template <typename Tfor func? It gets
the template parameter by the function signature, i.e the argument. func
will be instantiated based on Foo's template paramter T. This is why you
are getting complaints from gcc. No need for standard to understand that
this is an dubious declaration. Once you remove the function template
declaration, you create a binding that for any instance of Foo<T>, there
must be a func<Tdefinition that completes it unless it's never used
anywhere (but that's not the point here).

It's an completely different story when you say:
template<typename T>
class Foo {
public:
template<typename U>
friend void func (const Foo<U>& foo);

};

Here you U and T are orthogonal and Foo<Tand func<Uare too. You
don't create any binding between these two definitions (sort of, when
you invoke func, its template argument type is determined by its
argument). This is a common way to get different template instantiations
to work together. Not in this particular example, but for this one:
template <typename T>
class Foo {
public:
template<typename U>
Foo<T>& func (const Foo<U>& foo);

};

Foo<intfi;
Foo<floatff;
ff.func(fi);

A common use is to write copy constructors this way to convert between
different template instantation of types.
Thank you for your explanation.
Now the problem is much clearer to me.

Best Regards
StephQ
May 17 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Gianni Mariani | last post: by
10 posts views Thread by william xuuu | last post: by
5 posts views Thread by Pete C. | last post: by
7 posts views Thread by Noah Roberts | last post: by
9 posts views Thread by Klaas Vantournhout | last post: by
2 posts views Thread by Dave Rudolf | last post: by
12 posts views Thread by siddhu | last post: by
1 post views Thread by CARIGAR | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.