Question about bound template friend of template class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
template <typename T>
void show();

template <typename T>
class test
{
	T a;
public:
	test() :a(0){}
	test(int x) :a(x){}
	friend void show<T>();//bound template class
	friend void shown();//non-template class
	friend void showun(D &);//unbound template class
};


template <typename D>
void showun(D &x)
{
	cout << x.a;
}

void shown()
{
	cout << "hey";
}

test<int> a = 100;

template <typename T>
void show()
{
	cout << a.a;
}


My question is why "bound template class" need to offer an prototype before the class declaration while non-template class and unbound template class doesn't need to?
Last edited on
The name of a bound template friend is a dependant name; it is subject to 'two-phase name lookup'; the parser needs a little help during phase one.

The non-template and unbound template friends have non-dependant names.

See: http://www.cplusplus.com/forum/beginner/103508/#msg557627
http://www.parashift.com/c++-faq-lite/template-friends.html
Thanks to you again, JLBorges!

linkers you offered may be too involved to me for now... but I guess I can see a vague concept.
It's because the friend void show<T>(); is dependent to the template, so I have to put the template prototype before so that to the point of the friend declared inside class, the compiler will know there is a template the friend is from. Is that right?

Another question. the friend function declaration inside the class, is it also the prototype for the function definition? so I don't need to give another one before int main().
Last edited on
> It's because the friend void show<T>(); is dependent to the template,
> so I have to put the template prototype before so that to the point of the friend declared inside class,
> the compiler will know there is a template the friend is from. Is that right?

Yes.


> Another question. the friend function declaration inside the class,
> is it also the prototype for the function definition?

Yes, if there is no previous declaration of the function.

However:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

struct A ; int bar( A ) ; // bar declared at global namespace scope

struct A
{
    // int foo(A) is defined as a part of the friend declaration
    // 1. there is no previous declaration of int foo(A)
    // 2. the function int foo(a) has global namespace scope
    // 3. the function is implicitly inline
    // 4. however, it is within the lexical scope of class A
    // 5. therefore, it can only be found through ADL (Koenig lookup) unless it is        
    //         injected into the global namespace
    friend int foo( A a ) { return a.v * 2 ; }
    
    // int bar(A) is defined as a part of the friend declaration
    // 1. there is a previous declaration of int bar(A) at global namespace scope
    // 2. the previously declared function is being defined as part of the friend declaration
    // 3. the function is implicitly inline
    friend int bar( A a ) { return a.v * 2 ; }

    int v = 10 ;
};

int main()
{
    A a ;
    
    std::cout << foo(a) << '\n' ; // fine, int ::foo(A) found via ADL
    std::cout << bar(a) << '\n' ; // fine, int ::bar(A) declared at global namespace scope
    
    // std::cout << ::foo(a) << '\n' ; // *** error *** name ::foo not found
    std::cout << ::bar(a) << '\n' ; // fine, ::bar has been declared
    
    // std::cout << A::foo(a) << '\n' ; // *** error *** A does not have a member named foo
}

http://coliru.stacked-crooked.com/a/be5077aaa5e3239e
Last edited on
Thanks! I think I get what I wanna know from your reply.

For bound template function,

the instantiation inside the class is this format:
friend void show<T>();

but I remember the normal format is:
template void show<int>();

Why in the class the
template
missing?
> the instantiation inside the class is this format:
> friend void show<T>();

That is not instantiation; it is a declaration that void show<T>(); is a friend.

These are instantiations:
1
2
3
void foo() { show<int>() ; } // implicit instantiation 

template void show<double>(); // explicit instantiation 


Explicit instantiations are somewhat rare; for instance they can be used to reduce compilation time in programs spread over a large number of translation units (files).
See explicit instantiation in: http://en.cppreference.com/w/cpp/language/function_template
Topic archived. No new replies allowed.