uchar
uchar

Reputation: 2590

can not send const value to operator+ that use operator[][]

I want to implement a matrix class that use operator [][] .

I wrote the below code but the problem is that I cant send const value to operator+ !!(error: passing 'const Matrix' as 'this' argument of 'Matrix::Indexer Matrix::operator' discards qualifiers [-fpermissive])

If I change it to Matrix operator+(Matrix& other); It works fine...

I think I need two overload of Matrix::Indexer Matrix::operator[](int index) one for reading and one for writing to mat_ (like property in c# !) But how ?!

or may be I should use const_cast ?!

What is the best way to implement this class ?!

//Matrix.h 
class Matrix
{
public:
    Matrix(const int rows, const int cols, float defaultValue=0);
    //TODO copy constructor , destructor

    int rows() const;
    int cols() const;


    Matrix operator+(const Matrix& other);

    class Indexer
    {
    public:
        Indexer(float* arr,int cols);
        float& operator[](int index);
    private:
        float* arr_;
        int cols_;
    };

    Indexer operator[](int index);

private:
    int rows_;
    int cols_;
    float **mat_;

};

Matrix.cpp

#include "matrix.h"

Matrix::Matrix(const int rows, const int cols, float defaultValue) :
    rows_(rows),
    cols_(cols)
{
    mat_=new float*[rows_];

    for(int i=0;i<rows;i++)
    {
        mat_[i]=new float[cols];
    }

    for(int i=0;i<rows;i++)
    {
        for(int j=0;j<cols;j++)
        {
            mat_[i][j]=defaultValue;
        }
    }

}


int Matrix::rows() const
{
    return rows_;
}
int Matrix::cols() const
{
    return cols_;
}


Matrix::Indexer::Indexer(float* arr,int cols):
    arr_(arr),
    cols_(cols)
{}


Matrix::Indexer Matrix::operator[](int index)
{
    if(index>=rows_)
        throw "Out of row index";
    return Indexer(mat_[index],cols_);
}

float& Matrix::Indexer::operator[](int index)
{
    if(index>=cols_)
       throw "Out of cols index";
    return arr_[index];
}

 Matrix Matrix::operator+(const Matrix& other)//error
 {
     if(other.rows()!=this->rows()||other.cols()!=this->cols())
         throw "rows and cols are not equal";
     Matrix result(other.rows(),other.cols());
     for(int i=0;i<rows();i++)
     {
         for(int j=0;j<cols();j++)
         {
             result[i][j]=mat_[i][j]+other[i][j];//error: passing 'const Matrix' as 'this' argument of 'Matrix::Indexer Matrix::operator' discards qualifiers [-fpermissive
         }

     }
     return result;
 }

Upvotes: 0

Views: 216

Answers (2)

uchar
uchar

Reputation: 2590

I fixed my problem by adding

const Indexer operator[](int index)const;

and

const float& operator[](int index)const;

My code :

Matrix.h

#ifndef MATRIX_H
#define MATRIX_H

#include <iostream>

class Matrix
{
public:
    Matrix(const int rows, const int cols, float defaultValue=0);
    //TODO copy constructor , destructor

    int rows() const;
    int cols() const;


    Matrix operator+(const Matrix& other) const;

    class Indexer
    {
    public:
        Indexer(float* arr,int cols);
        const float& operator[](int index)const;
        float& operator[](int index);
    private:
        float* arr_;
        int cols_;
    };

    Indexer operator[](int index);
    const Indexer operator[](int index)const;

    friend std::ostream& operator<<(std::ostream& os,const Matrix& m);

private:
    int rows_;
    int cols_;
    float **mat_;
};

#endif // MATRIX_H

Matrix.cpp

#include "matrix.h"

Matrix::Matrix(const int rows, const int cols, float defaultValue) :
    rows_(rows),
    cols_(cols)
{
    mat_=new float*[rows_];

    for(int i=0;i<rows;i++)
    {
        mat_[i]=new float[cols];
    }

    for(int i=0;i<rows;i++)
    {
        for(int j=0;j<cols;j++)
        {
            mat_[i][j]=defaultValue;
        }
    }

}


int Matrix::rows() const
{
    return rows_;
}
int Matrix::cols() const
{
    return cols_;
}


Matrix::Indexer::Indexer(float* arr,int cols):
    arr_(arr),
    cols_(cols)
{}

const float &Matrix::Indexer::operator[](int index) const
{
    if(index>=cols_)
       throw "Out of cols index";
    return arr_[index];
}


Matrix::Indexer Matrix::operator[](int index)
{
    if(index>=rows_)
        throw "Out of row index";
    return Indexer(mat_[index],cols_);
}

const Matrix::Indexer Matrix::operator[](int index) const
{
    if(index>=rows_)
        throw "Out of row index";
    return Indexer(mat_[index],cols_);
}

std::ostream& operator<<(std::ostream &os, const Matrix &m)
{
    for(int i=0;i<m.rows();i++)
    {
        for(int j=0;j<m.cols();j++)
        {
            os<<m[i][j]<<" ";
        }
        os<<"\n";
    }
    return os;
}

float& Matrix::Indexer::operator[](int index)
{
    if(index>=cols_)
       throw "Out of cols index";
    return arr_[index];
}

 Matrix Matrix::operator+(const Matrix& other) const
 {
     if(other.rows()!=this->rows()||other.cols()!=this->cols())
         throw "rows and cols are not equal";
     Matrix result(other.rows(),other.cols());
     for(int i=0;i<rows();i++)
     {
         for(int j=0;j<cols();j++)
         {
             result[i][j]=mat_[i][j]+other[i][j];
         }

     }
     return result;
 }

Upvotes: 0

James Kanze
James Kanze

Reputation: 153929

Your operator+ should be a const member function, since it doesn't modify the object it is called on. For the rest, you'll probably need a ConstIndexer and an operator[]( int index ) const as well.

And totally unrelated to your question, but: you'd probably be better off using an std::vector<float> for the actual data. It's both easier to use, and (probably) faster.

Upvotes: 2

Related Questions