I've just started learning templates in C++ and for practice purposes wrote this simple code
#include <iostream>
template<typename T>
class A;
template<typename T>
std::ostream& operator<<(std::ostream& out, A<T> x);
template <typename T>
class A
{
T m_x = 10;
public:
A(T x) : m_x{ x } {}
friend std::ostream& operator<< <T>(std::ostream& out, A x);
};
template<typename T>
std::ostream& operator<<(std::ostream& out, A<T> x)
{
out << "m_x = " << x.m_x;
return out;
}
int main()
{
A<int> a1{ 10 };
std::cout << a1 << '\n';
}
It works as expected, that is I get 10
as the output, but there is one thing that bothers me. At which point is the operator<<
function instantiated? Does it happen at the point of creation of the a1
object (this is also the point where A<int>
is implicitly instatiated, right?) or does it happen when I call the operator<<
in std::cout << a1 << '\n'
? My guess is that the second option is correct and I base it on this excerpt from cppreference which says that:
When code refers to a function in context that requires the function definition to exist, or if the existence of the definition affects the semantics of the program (since C++11), and this particular function has not been explicitly instantiated, implicit instantiation occurs.
But is it true that a friend declaration does not require the function definition to exist?
I'm sorry if this question is ill-pharased, I did my best to use the nomenclature right, but I'm just a beginner.
EDIT
What about this?
template <typename T>
class foo
{
T m_x;
friend void bar(foo x)
{
x.m_x = "123";
}
};
if I put a friend function definition inside a class, every instantiation of that class causes a new, ordinary function overload to be created that takes an argument of the current specialization, hence I would expect to see an error as soon as I write this: foo<int> x;
but I don't get one... (for example, bar(x);
causes the error)