I currently have the following code that works:
class Element{
    public:
        int i;
        int j;
        int x;
};
class SparseMatrix{
    private:
        int m; 
        int n;
        int numElts;
        Element *ele;
    public:
        SparseMatrix(int m, int n, int numElts){
            this -> m = m;
            this -> n = n;
            this -> numElts = numElts;
            ele = new Element[this -> numElts];
        }
        
        ~SparseMatrix(){
            //destructor logic
        }
        SparseMatrix operator+(SparseMatrix &s);
        friend std::istream & operator>>(std::istream &is, SparseMatrix &s);
        friend std::ostream & operator<<(std::ostream &os, SparseMatrix &s);
};
SparseMatrix SparseMatrix::operator+(SparseMatrix &s){
    //addition logic
}
std::istream & operator>>(std::istream &is, SparseMatrix &s){
    //cin logic
}
std::ostream & operator<<(std::ostream &os, SparseMatrix &s){
    //cout logic
Notice that the member variable x in Element is hard-coded as an integer value.
Instead, I'd like to use the following templating:
template <typename T>
class Element{
    public:
        int i;
        int j;
        T x;
};
; the problem is that every time I try to percolate that change through the rest of my code, I'm left with half a million errors.
Note: I've tried so many different things from Stack Overflow that I'm not going to mention them here; believe me when I say: It's been a lot!
I'm a relative newbie, so can someone please tell me what templating measures I need to employ to arrive at error-free inheritance here? I would like SparseMatrix to accept and utilize the templated Element class, and I'd like the functions defined throughout to also work with the templated version of Element + SparseArray.
Update 1: This is in response to @user17732522's suggestion to do the seemingly straightforward templating.
Here's what I did:
template <typename T>
class Element{
    public:
        int i;
        int j;
        T x;
};
template <typename T>
class SparseMatrix{
    private:
        int m; 
        int n;
        int numElts;
        Element<T> *ele;
    public:
        SparseMatrix(int m, int n, int numElts){
            this -> m = m;
            this -> n = n;
            this -> numElts = numElts;
            ele = new Element<T>[this -> numElts];
        }
        ~SparseMatrix(){
            delete [] ele;
        }
        SparseMatrix operator+(SparseMatrix &s);
        friend std::istream & operator>>(std::istream &is, SparseMatrix &s);
        friend std::ostream & operator<<(std::ostream &os, SparseMatrix &s);
};
template <typename T>
SparseMatrix<T> SparseMatrix<T>::operator+(SparseMatrix<T> &s){
    //sum logic
}
template <typename T>
std::istream & operator>>(std::istream &is, SparseMatrix<T> &s){
    //cin logic
}
template <typename T>
std::ostream & operator<<(std::ostream &os, SparseMatrix<T> &s){
    //cout logic
}
What I get out from VSCode is 7 errors saying that more than one operator >> matches these operands, -Wnon-template-friend warnings, etc.
Did I miss something in my implementation?
