C++ custom assignment - c++

I have the following code:
template<size_t rows, size_t cols>
class Matrix{
std::array<int, rows * cols> data;
public:
int operator()(size_t i, size_t j){
return data[i * cols + j];
}
// ...code...
}
What is the best way to achieve this:
Matrix<1,1> a;
a(0, 0) = 0;
avoiding the lvalue required as left operand of assignment error?

You can change the following line:
int operator()(size_t i, size_t j){
To:
int & operator()(size_t i, size_t j){
Returning a refernce (L value reference to be precise) to the element in the Matrix will allow you to assign to it.
Update: Some notes to complete my answer:
As #user4581301 commented: you can see more info about C++ value categories here: What are rvalues, lvalues, xvalues, glvalues, and prvalues?
As #Darth-CodeX and #HolyBlackCat mentioned, it is advisable to add a const overload for operator():
int const & operator()(int i, int j) const { /* same implementation */ }
You can use it with a const Matrix for reading elements values: if you have e.g. a Matrix const & m, you can use int val = m(0,0) to read an element value (of cource you will not be able to use it for assignment due to constness).

You need to return the reference of the element from data like this:
// can change
int &operator()(size_t i, size_t j)
{
return data[i * cols + j];
}
And every STL container includes a const function, for the cases like const Matrix &
// cannot change
int operator()(size_t i, size_t j) const
{
return data[i * cols + j];
}

Related

operator overloading opertator + cant convert from pointer to const

i have a sparse matrix that is created with two arrays and each array index have a linked list the non zero numbers are in there including the i and j indexs
the header
class MNode {
public:
double _data;
int _indexI, _indexJ; // the place of the node in the matrix
// clarification: _nextRow is a pointer to the next columns in the row
MNode* _nextRow, *_nextCol;
MNode(double data, int i, int j);
};
private:
string _type;
MNode** _rowHead, **_colHead;
int _rowSize, _colSize;
int _elemNum;
void setValue(int, int, double);
void removeElement(int, int);
void insertNode(MNode*);
bool IsExist(int, int);
void setElementByType(int i, int j, double data);
public:
// construct a 'rows X cols' matrix.
SMatrix(int rows, int cols,string type);
// set the (i,j) element to be 'data'
void setElement(int i, int j, double data);
// destroy this matrix.
~SMatrix();
double getElement(int, int);
friend std::ostream& operator<<(std::ostream& os, const SMatrix& mat);
SMatrix& operator = (const SMatrix& other);
SMatrix & operator+(const SMatrix & other) const;
};
the cpp here is the overloading + function i get an erorr
cannot convert this pointer to const SMatrix to Smatrix&
SMatrix &SMatrix::operator +(const SMatrix& other) const {
SMatrix temp(3, 3, "any") ;
if (other._rowSize == this->_rowSize&&other._colSize == this->_colSize&&other._type == this->_type) {
for (int j = 0; j < other._colSize; j++) {
for (int i = 0; i < other._rowSize; i++) {
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
}
}
}
return temp;
}
here is the contructor
SMatrix::SMatrix(int rows, int cols,string matType )
{
_type = matType;
_rowSize = rows;
_colSize = cols;
_elemNum = 0;
_rowHead = new MNode*[rows];
if (!_rowHead)
{
cout << "allocation error";
exit(1);
}
_colHead = new MNode*[cols];
if (!_colHead)
{
cout << "allocation error";
exit(1);
}
for (int i = 0; i < rows; i++)
{
_rowHead[i] = NULL;
}
for (int i = 0; i < cols; i++)
{
_colHead[i] = NULL;
}
}
iam not sure what i need to do the signature of the function is given and cant be chanbged any idea?
You've declared other to be a reference to const:
SMatrix & operator+(const SMatrix & other) const;
^^^^^
You call the member function getElement on that reference:
temp.setElement(i, j, (other.getElement(i, j) + this->getElement(i, j)));
^^^^^^^^^^^^^^^^
You've declared getElement to be non-const:
double getElement(int, int);
^
You may only call const member functions on const references.
the signature of the function is given and cant be chanbged any idea?
If the signature of getElement can't be changed, then you've been dealt a badly written signature. There should be no good reason why a getter couldn't be const. That said, since you're within the class, you can access all members directly without using a getter.
There's another bug. You've declared operator+ to return a reference.
SMatrix &SMatrix::operator +(const SMatrix& other) const
^
But you return a local automatic variable temp:
SMatrix temp(3, 3, "any") ;
// ...
return temp;
Automatic variables are destroyed at the end of the function. Therefore the returned reference will always be dangling and any use of it would have undefined behaviour.
the signature of the function is given and cant be chanbged any idea?
If the signature of operator+ can't be changed, then you've been dealt a badly written signature. The function really should return by value. There's no sensible solution that could return a reference. Using a static local would technically work, but that has some limitations on usage that aren't apparent from the interface.

c++ - run on an object, operator overloading () with index

I have a class to represent two-dimensional array and I want to use () operator for example,
Array arr;
arr(2,5) = 17; // I want to assign 17 as element in 2nd row and 5th column.
I tried something like that: (but is not working)
void operator(int m, int n)(int num) {
int m, n;
p[m][n] = num;
}
i have an operator = (this working):
void operator=(const Array& other) const {
for (int i = 0; i < DIM; i++) {
for (int j = 0; j < DIM; j++) {
p[i][j] = other.p[i][j];
}
}
}
Array class has T** as private member.
How can I overload () operator to access elements in array
Thank You!
You need to build something like
int& operator()(int m, int n)
which returns a reference to the array element, that you can modify through that reference at the calling site.
Don't forget to build the const overload
const int& operator()(int m, int n) const
so you can use similar syntax at a call site for element access for a const object.
Finally, for your assignment operator, you ought not make it const (have you made p mutable?), and you should return a reference to self to help compound assignment:
Array& operator=(const Array& other){
// Your existing code
return *this;
}
Reference: http://en.cppreference.com/w/cpp/language/copy_assignment

Why write two () operators

Why do it twice?
These 2 lines, why do it like this way? Is one enough?
inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; }
const inline T& operator() (int row, int col) const { return this->m_data[row*NC + col]; }
thank you
*
* 2-DIMENSIONAL ARRAY
*
* Simulated by 1-dimension array.
******************************************************************************/
#ifndef __2D_ARRAY_H__
#define __2D_ARRAY_H__
#include <stdint.h>
#include <stdlib.h>
namespace alg {
/**
* 2D Array definition
*/
template <typename T=char>
class Array2D {
private:
uint32_t NR; // num of rows
uint32_t NC; // num of columns
T * m_data; // the place where the array resides.
public:
/**
* construct an array of size [nrow,col]
*/
Array2D(uint32_t nrow, uint32_t ncol) {
NR = nrow;
NC = ncol;
m_data = new T[nrow*ncol];
}
/**
* destructor
*/
~Array2D() {
delete [] m_data;
}
private:
Array2D(const Array2D&);
Array2D& operator=(const Array2D&);
public:
/**
* return number of rows of this array
*/
inline const uint32_t row() const { return NR; }
/**
* return number of columns of this array
*/
inline const uint32_t col() const { return NC; }
/**
* return the value by the given (row, col);
*/
inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; }
const inline T& operator() (int row, int col) const { return this->m_data[row*NC + col]; }
inline T* operator[] (int row) { return &(m_data[row * NC]); }
inline const T* operator[] (int row) const { return &(m_data[row * NC]); }
/**
* clear the array by a given value
*/
void clear(const T & value) {
for(uint32_t i=0; i<NR*NC;i++){
m_data[i] = value;
}
}
};
}
#endif //
One is const and the other is not.
The difference is that when you have a const reference to a Array2D you're only allowed to call member functions marked const. In this case that means the 2nd version, where it must necessarily return a const reference to the element it holds.
If you have a non-const reference, though, that 2nd version means you can't use operator() to make any changes to your Array2D.
If you look at standard library containers like std::vector you'll see that they do the same thing. You can get an iterator from begin() and a const_iterator from begin() const.
The first, non-constant version returns a reference that can be modified. If you have a constant object, you still want to be able to at least read the value, so you have to provide a second constant version.
The two () operators are not the same. inline T& operator() (int row, int col); returns a reference that allows the returned value to be modified. const inline T& operator() (int row, int col) const returns a reference that disallows the returned value from being modified. Also if the calling object is a const alg::Array2D&, than it can ONLY use the const operator();. So in order to allow users of the Array2D class to properly use const objects. It is best practice to implement both signatures for the operator ().
You could have a function void make_something (const Array2D<char> &input, Array2D<char> &output). This function lets input untouched, makes some operation with it, and writes the result to output. Reading from input would only be possible if there is also a const operator.
inline T& operator() (int row, int col) { return this->m_data[row*NC + col]; }
returns a non-const reference to the data in m_data[row * NC + col], which means I can do
auto& ref = obj(x, y);
ref = BAD_DATA;
and your object can't stop me. The const variant protects against this, and can be fingerprinted as const because it has no side effects on the object as a result.
inline const T& operator() (int row, int col) const { return this->m_data[row*NC + col]; }
This allows me to propagate constness outwards:
void myFunc(const Object& obj) /* I'm only going to look */
{
const auto& ref = obj(x, y);
std::cout << x << ',' << y << " = " << ref << '\n';
}

() = operator overload in class

I'm building a Matrix class for all the operations such as addition, subtraction, multiplication, inverse etc. I have overloaded simple operators such as + - () *. But I'm trying to set a row and column value via ().
A sample would be like so
Matrix(1,1) = 10;
assuming that row 1, column 1 would be set to 10.
A sample of my addition overload is this
friend Matrix operator +(Matrix&, Matrix&);
How can I achieve this?
Thanks!
Your matrix should provide element accessors, e.g. via operator():
template <typename T>
class Matrix
{
public:
T & operator()(size_t i, size_t j) { return buf[i * NCols + j]; } // Example
T const & operator()(size_t i, size_t j) const { /* same */ }
// ...
};
Then you can say:
Matrix<bool> m(20, 20);
m(12, 15) = false;
m(8, 19) = m(1, 2) = true;
return m(0, 0);
It's similar to what you've done already:
Value &operator()(int x, int y)
{
return matrix[x][y]; // or whatever it's supposed to be
}
, where Value is your internal type.
However, I suggest instead using a setter function, since it is far less ambiguous. e.g.:
void set(int x, int y, Value v)
{
matrix[x][y] = v;
}
Use
class Matrix {
T& operator()(size_t x, size_t y) {
return _mat[x][y]; //Or however your datastructure works
}
const T& operator() (size_t x, size_t y) const {
return _mat[x][y];
}
};
Where T is the datatype your matrix holds. Return the data at (x,y).

How to pass two-dimensional array as an argument?

My Matrx class is defined as
class Matrx
{
double A[50][50];
int m,n;
public:
Matrx(void);
Matrx(int a, int b)
{
m=a;
n=b;
}
Matrx operator +(Matrx b);
Matrx Transpose(Matrx b);
Matrx operator *(Matrx b);
CString printMatrx();
void readMatrx(double a[][]);
Matrx TransposeMat(Matrx b);
};
void Matrx::readMatrx(double a[][])
{
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
A[i][j]=a[i][j];
}
}
The intellisense gives error like the below
1 IntelliSense: an array may not have elements of this type d:\bmadaptive_dd_v1.02\matrx.h 17 27 TestServer
Why?
How to pass a two dimensional array as argument of the function?
The problem is that when passing multidimensional arrays as parameters in C++, you must specify the dimension of the outermost array. For example:
void ThisIsIllegal(int arr[][]); // Wrong!
void ThisIsAlsoIllegal(int arr[10][]); // Also wrong
void ThisIsLegal(int arr[][10]); // Okay
If you want to be able to have a function that takes in an array of any size, you can use templates:
template <size_t N, size_t M>
void ThisIsAlsoLegal(int (&arr)[M][N]);
This last version accepts any multidimensional array of the right type, and is probably what you're looking for.
You need to properly learn about arrays and pointers. This includes the lesson "huh! They are not as useful as I thought they were". After you've gotten familiar with how arrays and pointers work exactly you should rethink your design.
For example, in my opinion, the following design has lots of advantages:
#ifndef MATRIX_HPP_INCLUDED
#define MATRIX_HPP_INCLUDED
#include <vector>
#include <algorithm>
class matrix
{
public:
typedef std::vector<double>::size_type st;
matrix() : rows_(0), cols_(0) {}
matrix(int r, int c) : rows_(r), cols_(c), coeffs_(st(r)*c,0.0) {}
void reset(int r, int c)
{ rows_=r; cols_=c; coeffs_.clear(); coeffs_.resize(st(r)*c,0.0); }
int rows() const {return rows_;}
int cols() const {return cols_;}
double const& operator()(int i, int j) const {return coeffs_[indexof(i,j)];}
double & operator()(int i, int j) {return coeffs_[indexof(i,j)];}
double const* operator[](int i) const {return &coeffs_[indexof(i,0)];}
double * operator[](int i) {return &coeffs_[indexof(i,0)];}
void swap(matrix& that)
{
std::swap(this->rows_,that.rows_);
std::swap(this->cols_,that.cols_);
this->coeffs_.swap(that.coeffs_));
}
private:
int rows_, cols_;
std::vector<double> coeffs_;
st indexof(int i, int j) const {return st(i)*cols+j;} // row major storage
};
inline void swap(matrix& a, matrix& b) {a.swap(b);}
matrix& operator+=(matrix& lhs, matrix const& rhs);
matrix operator+(matrix const& lhs, matrix const& rhs);
matrix operator*(matrix const& lhs, matrix const& rhs);
inline matrix& operator*=(matrix& lhs, matrix const& rhs)
{ matrix tmp = lhs * rhs; swap(tmp,lhs); return lhs; }
...
#endif
This way you won't waste any space for small matrices, and you can support large matrices. Also, the use of std::vector instead of a pointer member which points to dynamically allocated memory removes the need to define your own copy constructor, assignment operator and destructor.
Of course, you could use boost::multi_array as a matrix replacement but using a custom matrix class allows you to declare overloaded operators in your own namespace which is desirable due to ADL (argument dependent lookup).
You might think that this doesn't really answer your question. In that case, let me stress that I think you don't fully understand how arrays and pointers work / behave. This is something you should look up in a decent C++ book. One could write many pages about this topic. You can't expect to see a short answer explaining all the quirks.
Check out the Definite C++ Book Guide thread.
You need to specify all but the first dimension, e.g.
void Matrx::readMatrx(double a[][50])
From this you should be able to see that you have a fundamental problem with the way you have implemented your class, but at least you should now be able to get the code to compile.
You can to specify all dimensions or only last dimension to pass an array:
void Matrx::readMatrx(double a[][50])
{
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
A[i][j]=a[i][j];
}
}
Thanks to all of you people...you were really helping...I have found myself a new definition of the class and the function definition for the matrix that fitted my need. I need you r comment on it...Below is the example of the class declaration..
#include<iostream>
#include"stdafx.h"
using namespace std;
const int M=100; const int N=100;
class Matrix
{
double A[M][N];
int m,n;
public:
Matrix(void);
Matrix(int a, int b)
{
m=a;
n=b;
for(int i=0;i<m;i++)
{
for(int j=0;j<m;j++)
A[i][j]=0.0;
}
}
Matrix operator +(Matrix b);
Matrix operator -(Matrix b);
Matrix operator *(Matrix b);
void TransPose(Matrix b);
CString printMatrix();
void readMatrix(double*);
};
and then the function implementation
#include "stdafx.h"
#include "Matrix.h"
Matrix::Matrix(void)
{
}
Matrix Matrix::operator *(Matrix b)
{
Matrix c(m,m);
if(n!=b.m)
{
HWND hndOwner(0);
MessageBoxW(hndOwner,L"Multiplication not possible row and column does not match",L"Error",NULL);
Matrix errMat(1,0);
double er[1][1]={0}; errMat.readMatrix((double *)er);
return errMat;
}
for(int i=0;i< m;i++)
{
for(int k=0;k< m;k++)
{
c.A[i][k]=0;
for(int j=0;j< n;j++)
{
c.A[i][k] = c.A[i][k]+(A[i][j] * b.A[j][k]) ;
}
}
}
return c;
}
Matrix Matrix::operator +(Matrix b)
{
Matrix c(m,n);
if((n!=b.n)||(m!=b.m))
{
HWND hndOwner(0);
MessageBoxW(hndOwner,L"Addition not possible row and column does not match",L"Error",NULL);
Matrix errMat(1,0);
double er[1][1]={0}; errMat.readMatrix((double *)er);
return errMat;
}
for(int i=0;i<m;i++)
{
for(int j=0;j< n;j++)
{
c.A[i][j]=0.0;
}
}
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
{
c.A[i][j]=A[i][j]+b.A[i][j];
}
}
return c;
}
CString Matrix::printMatrix()
{
CString strB(" "),strDisp;
for(int iRow=0;iRow<m;iRow++)
{
for(int iColumn=0;iColumn<n;iColumn++)
{
strB.Format(L"%lf ",A[iRow][iColumn]);
strDisp+=strB;
}
strDisp+="\r\n";
}
return strDisp;
}
void Matrix::readMatrix(double *ptrarr)
{
for(int i=0;i< m;i++)
{
for(int j=0;j< n;j++)
A[i][j]=*(ptrarr+i*n+j);
}
}
void Matrix::TransPose(Matrix b)
{
for(int i=0;i<b.n;i++)
{
for(int j=0;j<b.m;j++)
A[i][j]=b.A[j][i];
}
}
The simple codes in the above are working well till now...if you have any suggestion for the improvement please suggest..
You're lucky, then because:
for(int j=0;j<m;j++)
A[i][j]=0.0;
should probably be:
for(int j=0;j<**n**;j++)
A[i][j]=0.0;