Overloading << operator results in no output - c++

I am not sure if I am correctly overloading the << operator. The following code compiles without problem but does not produce the expected output.
#include <iostream>
#include "Matrix.h"
template<class T>
std::ostream& operator<<(std::ostream &out, const matrix<T> &A)
{
for(int ii = 0; ii << A.size(1); ii++)
{
for(int jj = 0; jj < A.size(2); jj++)
{
out << A(ii,jj) << " ";
}
out << std::endl;
}
return out;
}
int main(int argc, char** argv)
{
matrix<double> A = {{1.0, 2.0},{1.0,-1.0}};
cout << "\"" << A << "\"\n";
return 0;
}
The only output is:
""
Matrix.h
template<class T>
class matrix
{
public:
matrix(int rows, int cols);
matrix(const std::initializer_list<std::initializer_list<T>>& lst);
T& operator()(int i, int j);
T operator()(int i, int j) const;
int size(int n) const;
private:
int mRows;
int mCols;
std::vector<T> mData;
};
template<class T>
matrix<T>::matrix(int rows, int cols)
: mRows(rows),
mCols(cols),
mData(rows * cols)
{
}
template<class T>
matrix<T>::matrix(const std::initializer_list<std::initializer_list<T> >& lst)
: matrix(lst.size(), lst.size() ? lst.begin()->size() : 0)
{
int ii = 0, jj = 0;
for(const auto& l : lst)
{
for(const auto& v : l)
{
mData[ii*mCols + jj] = v;
jj++;
}
jj = 0;
ii++;
}
}
template<class T>
T& matrix<T>::operator()(int i, int j)
{
return mData[i*mCols + j];
}
template<class T>
T matrix<T>::operator()(int i, int j) const
{
return mData[i*mCols + j];
}
template<class T>
int matrix<T>::size(int n) const
{
if(n == 1)
{
return mRows;
}
else if(n == 2)
{
return mCols;
}
}

In your first for loop, you have:
for(int ii = 0; ii << A.size(1); ii++)
^
That should be a single < character:
for(int ii = 0; ii < A.size(1); ii++)
^
The reason why it wasn't doing anything is because the original loop resulted in a condition of 0 << A.size(1), which is 0, or false; thus, the outer loop is never executed.

Related

how to put all the numbers in the white boxes on the chessboardArray, in C++?

I wrote the following code for creating a chessboard using 2D Arrays in C++ :
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;
Here is the ChessBoardArray class:
class ChessBoardArray
{
protected:
class Row
{
public:
Row(ChessBoardArray &a, int i): cba(a), row(i){}
int & operator[] (int i) const
{
return cba.select(row, i);
}
private:
ChessBoardArray &cba;
int row;
};
class ConstRow
{
public:
ConstRow(const ChessBoardArray &a, int i): cba(a), row(i){}
int operator[] (int i) const
{
return cba.select(row, i);
}
private:
const ChessBoardArray &cba;
int row;
};
unsigned int my_size;
int my_base;
int *data;
The loc function is for finding the location of an element. It corresponds the elements of the 2D array to the corresponding position.
unsigned int loc(int i, int j) const throw(out_of_range)
{
int di = i - my_base, dj = j - my_base;
if(di < 0 || di >= my_size || dj < 0 || dj >= my_size) throw out_of_range("invalid index");
return di * my_size + dj;
}
public:
ChessBoardArray(unsigned size = 0, unsigned base = 0)
{
my_size = size;
my_base = base;
data = new int[my_size * my_size];
}
ChessBoardArray(const ChessBoardArray &a)
{
my_size = a.my_size;
my_base = a.my_base;
data = new int[my_size * my_size];
for(int i = 0; i < my_size*my_size; i++) data[i] = a.data[i];
}
~ChessBoardArray()
{
delete [] data;
}
ChessBoardArray & operator= (const ChessBoardArray &a)
{
this -> ~ChessBoardArray();
my_size = a.my_size;
my_base = a.my_base;
data = new int[my_size * my_size];
for(int i = 0; i < my_size*my_size; i++) data[i] = a.data[i];
return *this;
}
int & select(int i, int j)
{
return data[loc(i, j)];
}
int select(int i, int j) const
{
return data[loc(i, j)];
}
const Row operator[] (int i)
{
return Row(*this, i);
}
const ConstRow operator[] (int i) const
{
return ConstRow(*this, i);
}
friend ostream& operator<< (ostream &out, const ChessBoardArray &a)
{
for(int i = a.my_base; i <= a.my_size; i++)
{
for(int j = a.my_base; j <= a.my_size; j++)
{
out << setw(4) << a.data[a.loc(i, j)];
}
out << endl;
}
return out;
}
};
The condition for a number to be in a white box is i%2 == j%2. Where should i add the condition in my code?
I tried putting it inside the loc function but it got me some errors.

Matrix determinant in template using gaussian elimination

I'm having issues to implement the determinant of a matrix inside my matrix template. I'm trying to obtain the determinant by calculating the product of the principal diagonal in the reduced associated matrix. The problem is that it only works for some cases and is not reliable. This is the code for the determinant
template <typename T>
T Matrix<T>::Det() const {
if (Rows != Cols) {
cout << "Matrix must be square" << endl;
}
Matrix<T> r = Reduced();
T Det = 1;
for (int i=0; i<Rows; i++) {
Det *= r.getValue(i, i);
}
return Det;
}
Since the Gaussian elimination works, the reduced matrix that I obtain for any given matrix (which fits the criteria to be reduced) is fine, so i thought there wouldn't be any issue, but I haven't been able to see what I'm missing.
Any advice will be welcomed!
Edit:
As someone pointed out, here is a minimal reproducible example.
This would be the template
#ifndef MATRIX_H
#define MATRIX_H
#include <vector>
#include <iostream>
using namespace std;
template <typename T>
class Matrix {
private:
unsigned int Rows;
unsigned int Cols;
T *Mat;
public:
Matrix(unsigned int Dim);
Matrix(unsigned int Rows, unsigned int Cols);
Matrix(unsigned int Rows, unsigned int Cols, const std::vector<T>& Vec);
Matrix(unsigned int Dim, const std::vector<T>& Vec);
Matrix(const Matrix<T>& M);
~Matrix();
T& getValue(unsigned int Row, unsigned int Col) const;
T Det() const;
Matrix<T> Reduced() const;
};
template <typename T>
Matrix<T>::Matrix(unsigned int Rows, unsigned int Cols)
: Rows(Rows), Cols(Cols) {
if (Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = 0;
}
}
template <typename T>
Matrix<T>::Matrix(unsigned int Dim)
: Rows(Dim), Cols(Dim) {
if(Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = 0;
}
}
template <typename T>
Matrix<T>::Matrix(unsigned int Rows, unsigned int Cols, const std::vector<T>& Vec)
: Rows(Rows), Cols(Cols) {
if (Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
if (Vec.size() != Rows*Cols) {
cout << "Los tamaños de la matriz y el vector no son iguales" << endl;
}
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = Vec[i];
}
}
template <typename T>
Matrix<T>::Matrix(unsigned int Dim, const std::vector<T>& Vec)
: Rows(Dim), Cols(Dim) {
if (Rows<=0 || Cols<=0) {
cout << "Número inválido de filas o columnas" << endl;
}
Mat = new T[Rows*Cols];
if (Vec.size() != Rows*Cols) {
cout << "Número inválido de filas o columnas" << endl;
}
for (int i=0; i<Rows*Cols; i++) {
Mat[i] = Vec[i];
}
}
template <typename T>
Matrix<T>::Matrix(const Matrix<T>& M)
: Rows(M.Rows), Cols(M.Cols), Mat(new T[Rows * Cols]) {
for (int i = 0; i < Rows * Cols; i++)
Mat[i] = M.Mat[i];
}
template <typename T>
Matrix<T>::~Matrix() {
delete[] Mat;
}
template <typename T>
T &Matrix<T>::getValue(unsigned int Row, unsigned int Col) const {
if (Row<0 || Row>=Rows || Col<0 || Col>=Cols) {
cout << "Índice incorrecto" << endl;
}
return Mat[Row*Cols + Col];
}
template <typename T>
Matrix<T> Matrix<T>::Reduced() const {
if (Rows != Cols) {
cout << "La matriz debe ser cuadrada para reducirse" << endl;
}
Matrix<T> Tri(*this);
int n = Rows;
int m = 0;
for (int k=0; k<n-1; k++) {
if (Tri.Mat[k*Cols + k] == 0)
cout << "La matriz es singular" << endl;
for (int i = k+1; i<n; i++) {
m = Tri.Mat[i*Cols + k]/Tri.Mat[k*Cols + k];
for (int j = k+1; j<n; j++) {
Tri.Mat[i*Cols + j] = Tri.Mat[i*Cols + j] - m*Tri.Mat[k*Cols + j];
}
Tri.Mat[i*Cols + k] = 0;
}
}
return Tri;
}
template <typename T>
T Matrix<T>::Det() const {
if (Rows != Cols) {
cout << "Matrix must be square" << endl;
}
Matrix<T> r = Reduced();
T Det = 1;
for (int i=0; i<Rows; i++) {
Det *= r.getValue(i, i);
}
return Det;
}
template <class T>
ostream & operator<<(ostream &os, const Matrix<T> &Shw) {
for (int i=0; i<Shw.getRows(); i++) {
os << "| ";
for (int j=0; j<Shw.getCols(); j++) {
os << Shw.getValue(i,j) << " ";
}
os << "|\n";
}
return os;
}
#endif
This is the implementation on main.cc
#include "matrix.h"
int main() {
Matrix<double> M1(2, 2, {1, 3, 5, 7});
cout << M1.Det() << endl;
Matrix<double> M2(3, 3, {1, 3, 5, 7, 8, 9, 11, 2, 14});
cout << M2.Det() << endl;
return 0;
}
And the output is the following
-8 //This one is okay
-143 //This one is not
After a little inspection, I think I've found your problem.
You've made a simple mistake defining one of your key variables m. This is as you know, the main scaler in Gaussian elimination, and its job is to zero out the next row's element.
Instead of defining it as int m = 0 you should've defined it as float m = 0 or double m = 0.
Also, in the line that you calculate m you need to force cast the operands of the division to the appropriate types. So after redefining m, you should change this line:
m = Tri.Mat[i*Cols + k]/Tri.Mat[k*Cols + k]
to this
m = Tri.Mat[i*Cols + k] / (double)Tri.Mat[k*Cols + k]
Keep in mind that you're template type should be double as well or again this will not work.
Also, I recommend you to take a look at here to understand some of Gaussian Elimination's limits. There are some cases in which the algorithm will not work effectively.

Returning template class object

I have a template of a matrix class:
template <typename T>
class Matrix {
And many functions (like adding two matrices) return std::optional. I wanted to make an operator that would unwrap the value (or throw an exception):
template <class T>
Matrix<T> operator!(const std::optional<Matrix<T>>& other) {
return other.value();
}
Doing that I get the error C2440: "Cannot convert from const _Ty to Matrix< int > with [ _Ty = Matrix]". It says that construction of Matrix class cannot be done because of ambiguous copying constructors or unavailable copying constructor.
EDIT:
#include <iostream>
#include <optional>
template <typename T>
class Matrix {
private:
T** matrix;
int sizeX;
int sizeY;
public:
Matrix(int x, int y);
Matrix(Matrix<T>& other);
Matrix(Matrix<T>&& other);
void set_value(T val, int x, int y);
std::optional<Matrix<T>> vec_from_col(int colIndex);
};
template <typename T>
Matrix<T>::Matrix(int x, int y) {
std::cout << "Matrix Param\n";
if (x <= 0 || y <= 0) {
return;
throw -1;
}
else {
matrix = new T*[x];
for (int i = 0; i < x; i++) {
matrix[i] = new T[y];
for (int j = 0; j < y; j++) {
matrix[i][j] = 0;
}
}
sizeX = x;
sizeY = y;
}
}
template <typename T>
Matrix<T>::Matrix(Matrix<T>& other) {
std::cout << "Matrix Copy\n";
sizeX = other.sizeX;
sizeY = other.sizeY;
matrix = new T*[sizeX];
for (int i = 0; i < sizeX; i++) {
matrix[i] = new T[sizeY];
for (int j = 0; j < sizeY; j++) {
matrix[i][j] = other.matrix[i][j];
}
}
}
template <typename T>
Matrix<T>::Matrix(Matrix<T>&& other) {
std::cout << "Matrix Move\n";
sizeX = other.sizeX;
sizeY = other.sizeY;
matrix = other.matrix;
other.matrix = NULL;
}
template <typename T>
void Matrix<T>::set_value(T val, int x, int y) {
if (x < 0 || x >= sizeX || y < 0 || y >= sizeY) {
std::cout << "Invalid index was given. Matrix was unchanged.\n";
return;
}
else {
matrix[x][y] = val;
}
}
template <typename T>
std::optional<Matrix<T>> Matrix<T>::vec_from_col(int colIndex) {
if (colIndex < 0 || colIndex >= sizeX) {
return {};
}
Matrix<T> newVec(1, sizeY);
for (int i = 0; i < sizeY; i++) {
newVec.set_value(matrix[colIndex][i], 0, i);
}
return newVec;
}
template <class T>
Matrix<T> operator!(const std::optional<Matrix<T>>& other) {
return other.value();
}
int main() {
Matrix<int> test(2, 3);
test.set_value(10, 0, 1);
test.set_value(5, 0, 0);
test.set_value(13, 0, 2);
test.set_value(8, 1, 0);
Matrix<int> vec = !test.vec_from_col(0);
}
Your copy constructor is wrong which causes this ambiguity.
Matrix(Matrix<T>& other);
should be
Matrix(const Matrix<T>& other);
Note: You also leak memory since you new[] but don't delete[].

C++ Matrix Operator+

The method template <class T> const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const for program matrix.cc should be able to return the sum of calling object's matrix and rhs's matrix as a new object. Also, the lhs and rhs rows and cols will be equal.
The error output that I am receiving from the compiler is:
[hw7] make clean && make bin/test_add && ./bin/test_add UserSettings ✱
rm -f bin/*
g++ -std=c++11 -Wall -I inc -I src -c src/test_matrix_add.cc -o bin/test_matrix_add.o
g++ -std=c++11 -Wall -I inc -I src -o bin/test_add bin/test_matrix_add.o
Testing Matrix::operator+
Expected Matrix2[0][0]: 3.0, Actual: 1
FAILED
Could someone let me know why I receive this "Failed" output when I know I pass the // TEST MUL ASSIGMENT OP CORRECT RETURN section.
Here is my matrix.cc:
#include <matrix.h>
template <class T>
Matrix<T>::Matrix() {
rows_ = 0;
cols_ = 0;
m_ = nullptr;
}
template <class T>
Matrix<T>::Matrix(unsigned int rows, unsigned int cols)
: rows_(rows), cols_(cols) {
m_ = new T *[rows_];
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
}
}
template <class T>
Matrix<T>::Matrix(const Matrix<T> &that) {
rows_ = that.rows_;
cols_ = that.cols_;
m_ = new T *[rows_];
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] = that.m_[i][j];
}
}
}
template <class T>
Matrix<T>::~Matrix() {
for (unsigned int i = 0; i < rows_; ++i) {
delete[] m_[i]; // delete columns
}
delete[] m_; // delete columns
}
template <class T>
T Matrix<T>::Get(unsigned int row, unsigned int col) const {
if (row > rows_ && col > cols_) {
throw std::out_of_range("error: index out of range");
}
return this->m_[row][col];
}
template <class T>
const Matrix<T> &Matrix<T>::operator=(const Matrix<T> &rhs) {
if (this == &rhs) {
return *this;
} // returns the address
for (unsigned int i = 0; i < rows_; ++i) {
delete[] m_[i];
}
delete[] m_;
rows_ = rhs.rows_;
cols_ = rhs.cols_;
m_ = new T *[rows_];
for (unsigned int i = 0; i < rows_; ++i) {
m_[i] = new T[cols_];
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] = rhs.m_[i][j];
}
}
return *this;
}
template <class T>
const Matrix<T> &Matrix<T>::operator*=(T rhs) {
for (unsigned int i = 0; i < rows_; ++i) {
for (unsigned int j = 0; j < cols_; ++j) {
m_[i][j] *= rhs;
}
}
return *this;
}
template <class T>
const Matrix<T> Matrix<T>::operator+(const Matrix<T> &rhs) const {
if (!(this->cols_ == rhs.cols_) || (this->rows_ == rhs.rows_)) {
std::cout << "Cannont add matrices. Wrong dimensions\n";
exit(0);
}
Matrix<T> lhs;
lhs.rows_ = this->rows_;
lhs.cols_ = this->cols_;
for (unsigned int i = 0; i < lhs.rows_; ++i) {
for (unsigned int j = 0; j < lhs.cols_; ++j) {
lhs[i][j] += rhs[i][j];
}
}
return lhs;
}
Here is my matrix.h:
#include <cassert>
// using assert
#include <exception>
#include <iostream>
template <class T>
class Matrix {
public:
friend class MatrixTester;
Matrix(); // for testing, useless in practice
Matrix(unsigned int rows, unsigned int cols);
Matrix(const Matrix<T> &that);
~Matrix();
T Get(unsigned int row, unsigned int col) const;
const Matrix<T> &operator=(const Matrix<T> &rhs);
const Matrix<T> &operator*=(T rhs);
const Matrix<T> operator+(const Matrix<T> &rhs) const;
private:
T **m_;
unsigned int rows_;
unsigned int cols_;
};
#include <matrix.cc> //NOLINT
This is my test_matrix_add.cc tester:
#include <test_matrix.h>
int main(int argc, char** argv) {
MatrixTester tester;
cout << "Testing Matrix::operator+" << endl;
if (tester.Test_AddOp()) {
cout << " PASSED" << endl;
return 0;
}
cout << " FAILED" << endl;
return 1;
}
bool MatrixTester::Test_AddOp() const {
const int kRows = 4, kCols = 5;
Matrix<double> m1;
m1.m_ = new double*[kRows];
for (unsigned int i = 0; i < kRows; ++i) {
m1.m_[i] = new double[kCols];
for (unsigned int j = 0; j < kCols; ++j)
m1.m_[i][j] = (i + 1.0) * (j + 1.0);
}
m1.rows_ = kRows;
m1.cols_ = kCols;
// TEST ADDITION CORRECTNESS
Matrix<double> m2;
m2 = m1;
// + m1 + m1;
if (m2.m_[0][0] != 3) {
cout << " Expected Matrix2[0][0]: 3.0, Actual: " << m2.m_[0][0] << endl;
return false;
}
if (m2.m_[1][3] != 24.0) {
cout << " Expected Matrix2[1][3]: 24.0, Actual: " << m2.m_[1][3] << endl;
return false;
}
if (m2.m_[2][2] != 27.0) {
cout << " Expected Matrix2[2][2]: 27.0, Actual: " << m2.m_[2][2] << endl;
return false;
}
if (m2.m_[3][4] != 60.0) {
cout << " Expected Matrix2[2][2]: 60.0, Actual: " << m2.m_[2][2] << endl;
return false;
}
return true;
}
Firstly, there is way too much code here.
To address your problem, I see don't see you allocating memory to lhs.m_. This is a problem because you initialize lhs with the default constructor, which only assigns this->m_ to a nullptr.
To fix this, this should work (although untested):
template <class T>
const Matrix<T> Matrix<T>::operator+(const Matrix<T>& rhs) const
{
if (!(this->cols_ == rhs.cols_) || (this->rows_ == rhs.rows_))
{
std::cout << "Cannot add matrices. Wrong dimensions\n";
exit(0);
}
Matrix<T> lhs;
lhs.rows_ = this->rows_;
lhs.cols_ = this->cols_;
// Allocate memory for `lhs.m_`, like you did in your 2nd constructor
lhs.m_ = new T* [rows_];
for (unsigned i = 0; i < rows_; ++i)
{
m_[i] = new T[cols_];
}
// [End] allocation
for (unsigned int i = 0; i < lhs.rows_; ++i)
{
for (unsigned int j = 0; j < lhs.cols_; ++j)
{
lhs[i][j] += rhs[i][j];
}
}
return lhs;
}
Also, somewhat unrelated, be careful that you consistently treat m_ as a double-pointer. I didn't read all your code, but just be cautious. And also remember that you have to deallocate all the memory you allocated with new in your destructor. Personally, I believe you should use smart pointers from <memory> (e.g. std::unique_ptr, etc), which you can learn more about here. Using smart pointers would make the pointers deallocate the memory on their own and you wouldn't have to worry about memory leaks.
Edit 1
As walnut stated, a better solution would be to just call the 2nd constructor, which will allocate the memory for you. So, your revised function would be:
template <class T>
/**
Note:
> When you call this function (e.g. Matrix<T> new_mat = mat1 + mat2),
`mat1` is `this` and `mat2` is what you're calling `rhs`. I've done
some renaming and corrected your logic errors here
*/
const Matrix<T> Matrix<T>::operator+(const Matrix<T>& other) const
{
if (!(this->cols_ == other.cols_) || (this->rows_ == other.rows_))
{
std::cout << "Cannot add matrices. Wrong dimensions\n";
exit(0);
}
// Call the 2nd constructor
Matrix<T> res(this->rows_, this->cols_);
for (unsigned i = 0; i < res.rows_; ++i)
{
for (unsigned j = 0; j < res.cols_; ++j)
{
res.m_[i][j] = this->m_[i][j] + other.m_[i][j];
}
}
return res;
}
Edit 2
The above code has been correct to add the matrices correctly, as per #walnut's comment.

Weird segmentation fault 11

There are two files:
Matrix.hpp:
template <typename T>
class Matrix {
private:
size_t rows = 0;
size_t cols = 0;
T* data = nullptr;
public:
Matrix() = default;
~Matrix();
Matrix(size_t n, size_t m);
T& operator() (size_t i, size_t j);
};
template <typename T>
Matrix<T>::Matrix(size_t n, size_t m) : rows(n), cols(m) {
try {
data = new T[rows*cols];
} catch (const std::bad_alloc& e) {
std::exit(EXIT_FAILURE);
}
};
template <typename T>
Matrix<T>::~Matrix() {
delete[] data;
}
template <typename T>
T& Matrix<T>::operator()(size_t i, size_t j) {
if (i < rows && i >= 0 && j < cols && j >= 0) {
return data[(i+1)*cols + (j+1)];
} else {
throw std::logic_error("matrix indices out of range");
}
}
and
Main.cpp:
#include <iostream>
#include "Matrix.hpp"
int main() {
size_t n, k;
std::cin >> n >> k;
Matrix<long double> m = {n, k};
for (size_t i = 0; i < m.getNumRows(); ++i) {
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cin >> m(i,j);
}
}
for (size_t i = 0; i < m.getNumRows(); ++i) {
std::cout << "\n";
for (size_t j = 0; j < m.getNumCols(); ++j) {
std::cout << m(i, j) << " ";
}
}
return 0;
}
When I'm entering something like:
1 2 3 4
I can get
3 4
as answer but sometimes the same input causes Segmentation fault 11 moreover when I'm changing template argument from long double to int, error disappears. How can I fix it?
Your operator function is accessing data outside its bounds.
Passing (0,0) to the function should return data[0]. Currently it returns data[2].
Change line
return data[(i+1)*cols+(j+1)];
to
return data[i*cols+j];