template <typename T>
void show();
template <typename T>
class test
{
T a;
public:
test() :a(0){}
test(int x) :a(x){}
friendvoid show<T>();//bound template class
friendvoid shown();//non-template class
friendvoid 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?
linkers you offered may be too involved to me for now... but I guess I can see a vague concept.
It's because the friendvoid 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().
> 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.
#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
friendint 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
friendint 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
}
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