Why code doesn't work
Making the following announcements:
friend ostream& operator << (ostream &, const Matrix<T> &); friend istream& operator >> (istream &, Matrix<T> &);
You tell the compiler, somewhere there are functions that take threads as the first argument and Matrix<T>
second. But Matrix<T>
is not a template here, contrary to what may seem - the template is the Matrix
class, and Matrix<T>
here is a very specific implementation that will be known when the template is instantiated. Moreover, no code at all exists until the template has been instantiated.
Based on this, our friend-declarations only take effect when a template is instantiated. Let's, for example, create a Matrix<int>
. This gives us the following code generated for our template:
friend ostream& operator << (ostream &, const Matrix<int> &); friend istream& operator >> (istream &, Matrix<int> &);
Those. As you can see, we have two non - template friend declarations. On the other hand, we have an implementation of a template operator (I’ll only give one for short):
template< typename T> std::ostream & operator<<(std::ostream & os, const Matrix<T> & rhs) { ... }
If it seems to you that an ad in a class and a definition outside it should be somehow related, then this is not so. These are two completely different functions (one is template and the other is not), and since, according to the ADL (argument-dependent lookup), when the operator is called, the proper function is searched in the class, the compiler finds our friend-declaration:
friend ostream& operator << (ostream &, const Matrix<int> &);
But there is no implementation of this declaration, hence the linker error. In the forehead, for the type int
, this could be corrected in the following way; we need to fix our implementation with the following:
std::ostream & operator<<(std::ostream & os, const Matrix<int> & rhs) { ... }
Now our operator has ceased to be a template, and therefore it is the implementation of our friend declaration for the template instantiated for int
.
How to fix
Of course, this does not suit us - let us not write the implementation for each type of instantiation. Therefore, we need to write a friend declaration so that it always takes into account the type T
How to do it? It is necessary to have a template statement, as you did before, i.e. we leave the old implementation:
template< typename T> std::ostream& operator<<(std::ostream & os, const Matrix<T> & rhs) { ... }
But now, in the Matrix
class, we will add a specialization of this template to friends:
friend ostream& operator <<<T>(ostream & os, const Matrix & rhs); friend istream& operator >><T>(istream &, Matrix &);
And since we declare a specialization to be a friend, we have to move the definition (or just the declaration) of the general template to the Matrix
class, i.e. Your entire code will look like this:
template<typename T> class Matrix; template< typename T> std::ostream& operator<<(std::ostream & os, const Matrix<T> & rhs) { ... } template< typename T> std::istream & operator>>(std::istream& is, Matrix<T> & rhs) { ... } template<typename T> class Matrix { private: T arr[SIZE][SIZE]; friend ostream& operator <<<T>(ostream &, const Matrix &); friend istream& operator >><T>(istream &, Matrix &); ... };
Another correct option, with a minimum of changes, could be:
friend ostream& ::operator << (ostream &, const Matrix<T> &); friend istream& ::operator >> (istream &, Matrix<T> &);
But it works only in the studio, clang & gcc do not accept this code.
int
and inQVector
size here . - αλεχολυτint
protection? If yes, then it is unconvincing. The guys who worked and are working on Qt are not authority, absolutely. - ixScistd::
should not, IMHO, be the subject of controversy here. As they say, in a strange monastery with its charter ... - αλεχολυτ