Create a class template for an array

file myArray.h

#ifndef myArray_h #define myArray_h #include <iostream> using std::istream; using std::ostream; template <typename T> class myArray //созданиС шаблона класса myArray { T** mas; //ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π΄Π²ΡƒΠΌΠ΅Ρ€Π½Ρ‹ΠΉ массив int line, //ΠΊΠΎΠ»-Π²ΠΎ строк column; //ΠΊΠΎΠ»-Π²ΠΎ столбцов friend istream& operator >> (istream& in, const myArray& el) //ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° Π²Ρ‹Π²ΠΎΠ΄Π° >> { for (int i = 0; i < el.line; i++) { for (int j = 0; j < el.column; j++) { in >> el.mas[i][j]; } } return in; } public: myArray() { mas = 0; //конструктор Π±Π΅Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² line = 0; column = 0; } myArray(int n, int m); //ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ конструктора с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ myArray(const myArray& masToCopy); //ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ конструктор копирования ~myArray() //дСструктор { for (int i = 0; i < line; i++) { delete[](mas[i]); } delete[](mas); } friend myArray <T> operator +(const myArray<T>&, const myArray<T>&); //ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° слоТСния + }; template <typename T> myArray <T>::myArray(int n = 1, int m = 1) : line(n), column(m) //конструктор с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ { mas = new int* [n]; for (int i = 0; i < n; i++) { mas[i] = new int[m]; } } template <typename T> myArray <T>:: myArray(const myArray& masToCopy) // конструктор копирования { line = masToCopy.line; column = masToCopy.column; mas = new int* [line]; // для Π½ΠΎΠ²ΠΎΠΉ ΠΊΠΎΠΏΠΈΠΈ for (int i = 0; i < line; i++) mas[i] = new int[column]; for (int i = 0; i < line; i++) for (int j = 0; j < column; j++) mas[i][j] = masToCopy.mas[i][j]; } template <typename T> myArray <T> operator+(const myArray<T>& m1, const myArray<T>& m2) //ΠΏΠ΅Ρ€Π΅Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° слоТСния + { for (int i = 0; i < m1.line; i++) { for (int j = 0; j < m1.column; j++) { m1.mas[i][j] = m1.mas[i][j] + m2.mas[i][j]; } } return m1; } 

main.cpp file

 #include "stdafx.h" #include <iostream> #include "myArray.h" using std::cout; using std::endl; int main() { myArray<int> intArray1(2, 2); myArray<int> intArray2(2, 2); myArray<int> A = intArray1 + intArray2; cout << A; return 0; } 

Produces such an error mistake

How can I fix it?

    2 answers 2

    The declaration of the operator + friend function you made refers to a non-generic function with myArray<T> parameters for each variant of your myArray<T> template. That is, in your particular example, the usual non-template function is declared to be a friend for the class myArray<int>

     myArray<int> operator +(const myArray<int> &, const myArray<int> &); 

    This function is the best candidate for a call at calculation intArray1 + intArray2 . It is this function that the compiler will attempt to invoke. But since such a function is not defined anywhere in your code, an error will occur.

    If you want for the myArray<T> class myArray<T> friend, it is the specific specialization of the operator + function template you defined below, you need to declare this template to be a friend of your class. For what it is necessary to use a slightly different approach and syntax.

    First, you must declare an operator + function template in advance (even before your class is defined)

     template <typename T> class myArray; template <typename T> myArray<T> operator +(const myArray<T> &, const myArray<T> &); 

    Secondly, after this, in a friend-declaration inside the class definition, you should refer to this template using the syntax with <> after the function name

     template <typename T> class myArray { ... friend myArray<T> operator +<>(const myArray<T> &, const myArray<T> &); }; 

    The member functions of the class templates themselves are templates. The C ++ language prohibits the "addition" of arguments by default in repeated declarations of function templates. (This is possible only for ordinary non-generic functions.) All arguments by default must be present in the very first declaration of the function template.

    In your case, if you want to use the default arguments in the constructor

     template <typename T> myArray<T>::myArray(int, int) 

    these arguments must be specified immediately, directly in the declaration of this constructor inside the class definition. It is impossible to add arguments by default later. Your default arguments are specified later - in the definition of this template function. It is not compilable in C ++. Therefore, how you managed to get to the link error with this code, which is not compiled at all (including due to other errors), it is not clear to me.

    On SO it is recommended to present the real code, and not false fabrications "based on".

    • Something you have is too difficult, no? It is quite enough to correctly declare a friend as template<typename U> friend myArray <U> operator +(const myArray<U>&, const myArray<U>&); - Harry
    • @Harry: First, I am for meticulous accuracy. Secondly, my goal is not confined to the banal "fix it somehow to compile," but in explaining how this feature of the language works. In the variant proposed by you, it will turn out that all + are friends of all myArray . Those. the addition operator for myArray<double> will be a friend for the class myArray<SomeClass> , etc. and so on in any combination. - AnT
    • And C ++ allows you to restrict yourself to "exact" friendliness: the addition operator for myArray<int> is different only for myArray<int> (I am sure that this was the intention of the author). But for this you need to take a number of additional gestures. Whether the author wants to spend these extra efforts or does not want is already a separate question. - AnT
    • I'm trying to figure out how to abuse the fact that + will be a friend for all myArray . I can not figure out how it can be dangerous, do not tell? Only without options in the implementation intentionally use different types of arrays, for example myArray<int> and myArray<double> . - Harry
    • @Harry: Firstly, I don’t quite understand the logic of choosing a language feature based on whether it can or cannot be "abused". (It is not difficult to abuse something - you yourself gave an example.) But, secondly, this is not about suppressing attempts at abuse, but simply about how to express the author's intention precisely. I want (and that is enough for me) that my myArray<int> friend is exactly and only operator +<int> . This is a completely natural desire. That is what we need. My answer shows how to do it right. - AnT

    First, you have not declared operator operator << . Therefore, this proposal

     cout << A; 

    is erroneous.

    Secondly, you have constructors in conflict, because you overdid it with the default arguments. In this regard, the compiler will not be able to select the correct constructor.

    You could declare constructors as follows.

     myArray() : mas( 0 ), line( 0 ), column( 0 ) {} //конструктор Π±Π΅Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ² myArray(int n, int m); //ΠΏΡ€ΠΎΡ‚ΠΎΡ‚ΠΈΠΏ конструктора с ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π°ΠΌΠΈ 

    And for the second constructor, do not specify the default arguments in its definition.

    As for operator + , it should be declared in the class as a template function. For example,

     template <typename U> friend myArray <U> operator +(const myArray<U> &, const myArray<U> &);