0

I define the square matrix by a 2D dynamic array with the new operator following:

int n, i{0};
int value;

do {
    cin >> n;
} while ((n <=0) || (n > 20));

int* pMatrix = new int [n*n];
if(pMatrix == NULL) return 1;

do {
    cin >> value;
    *(pMatrix + i) = value;
    i++;
} while (i < (n*n));

Then I have tried to print that array out by operator << overloading, following:

template <typename customizedType, int matrixEdge>
ostream& operator<< (ostream &os, const customizedType* inputMatrix[matrixEdge]) {
    os << "{ ";
    for (int i = 0, matrixSize = matrixEdge*matrixEdge; i < matrixSize; i++) {
        os << *(inputMatrix + i) << ' ';
        if (((i+1) % matrixEdge) == 0 && (i < matrixSize-1)) {os << '}' << endl; os << "{ ";}
    }
    os << '}' << endl;
    return os;
}

Please help me to make it work! I could solved that as the function void printing2DArray(...), but just want to do that with operator << overloading. Thank you.

8
  • 4
    Why do you use raw C array with manual new instead of std::vector ? It is recommended anyway, and will also make overloading operator<< easier. Commented Sep 17, 2024 at 3:58
  • 4
    This is very bad code. Define a class called Matrix and work with it. Don't pepper your code with raw pointers. Your pMatrix is int* not int* [something]. You cannot recover the number of elements from a raw pointer. Commented Sep 17, 2024 at 4:05
  • 1
    FYI: if(pMatrix == NULL) is useless here since pMatrix can never be null here. Will new operator return NULL? and Why doesn't new in C++ return NULL on failure Commented Sep 17, 2024 at 4:10
  • 2
    Side notes, learn about rangebased for loops and stop using endl and using namespace std;. I would also expext that you would make a Matrix class and then use ostream& operator<< (ostream &os, const Matrix<customizedType>&. A pointer is NOT a matrix Commented Sep 17, 2024 at 4:10
  • 2
    In general don't overload operators for types you don't own. Specially not in the global namespace. Commented Sep 17, 2024 at 4:14

1 Answer 1

3

You'd normally do this by creating a class to hold your 2-D matrix, then overloading operator<< for instances of that class:

template <class T>
class matrix2d {
    std::vector<T> data;
    std::size_t cols;
    std::size_t rows;
public:
    matrix2d(std::size_t y, std::size_t x) : cols(x), rows(y), data(x*y) {}
    T &operator()(std::size_t y, std::size_t x) { 
        assert(x<=cols);
        assert(y<=rows);
        return data[y*cols+x];
    }
    T operator()(std::size_t y, std::size_t x) const {
        assert(x<=cols);
        assert(y<=rows);
        return data[y*cols+x];
    }

    friend std::ostream &operator<<(std::ostream &os, matrix2d const &m) {
        for (std::size_t y=0; y<m.rows; y++) {
            for (std::size_t x = 0; x<m.cols; x++) {
                os << m(y,x) << "\t";
            }
            os << "\n";
        }
        return os;
    }
};

live on Godbolt

Sign up to request clarification or add additional context in comments.

5 Comments

T operator()(size_t y, size_t x) const Don't you mean const T& operator()(size_t y, size_t x) const ?
@PepijnKramer: could go either way on that. I'm assuming it's primarily for numerical types that we don't particularly mind copying, so we only use references where needed, but there are certainly cases where you wouldn't want that.
Ok, I just have tendency to add some SFINAE (or concepts) on my T. So if I assume "cheap to copy" I would constrain T to some concept of "cheap to copy"
@PepijnKramer: In practical use, that's a perfectly reasonable thing to do. But the single responsibility principle applies as much to code in answers as anywhere else. The sole responsibility of this code is to give somebody the general idea of how to overload operator<< for a matrix-like object, not to try to be a complete (or really even partial) replacement for std::valarray, Eigen, etc. Yes, I try to avoid things I think are bad (e.g., raw new and delete), but not at the expense of fulfilling its primary goal.
@JerryCoffin Fair comments :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.