Why write two () operators - c++

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';
}

Related

C++ custom assignment

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];
}

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.

Is it safe to cast away const if never call any non-const methods

Is it still undefined behavior to cast away const from a pointer to an object if only const methods are ever be called after the cast?
I'm trying to implement both an iterator and const_iterator for a class where the dereferenced iterator is a proxy object with a small amount of state and a pointer to the parent object (simplified below)
Although the const qualified proxy only calls const methods on the parent it still requires a non-const pointer in the constructor.
class query {
public:
int get (int r, int c) const;
void set (int r, int c, int v);
class iterator {
iterator (query *q, int r) : m_qry(q), m_row(r) {}
row operator* const () { return row(m_qry, m_row); }
query *m_qry;
int m_row;
};
class const_iterator {
const_iterator (const query *q, int r) : m_qry(q), m_row(r) {}
const row operator* const () {
// protected constructor for row needs cast
return row(const_cast<query *>(m_qry), m_row);
}
const query *m_qry;
int m_row;
};
iterator begin() { return iterator(this, 0); }
const_iterator begin() { return const_iterator(this, 0); }
};
class row {
friend query;
public:
int get (int col) const {
// can be called by both row and const row
return m_qry->get(m_row, col);
}
void set (int col, int v) {
// cannot be called for const row
return m_qry->set(m_row, col, v);
}
protected:
row (query *q, int row) : m_qry(q), m_row(r) {}
private:
query *m_qry;
int m_row;
};
I would prefer to avoid using different classes for the differing iterators as this would require considerable code duplication.
If this is not possible are there any other alternative design patterns with good performance?
In a const method, the this pointer is a const type.
So given that it's implicitly cast back to const, the behaviour is well defined.

C++: Non-const operator taking preference over const overload

I have a class that represents a diagonal matrix. I only store the elements along the diagonal, so I don't waste space with a bunch of 0's. However, I still want to be able to use double brackets to access elements in the array. To get around that, I use an inner class, like this:
template <class T>
class DiagonalMatrix
{
private:
const T ZERO = 0;
int _size;
Vector<T> _data;
class row
{
private:
DiagonalMatrix<T>* _parent;
int _row;
public:
row(DiagonalMatrix<T>* parent, const int row)
: _parent(parent), _row(row) {}
T& operator[](const int i);
};
class const_row
{
private:
const DiagonalMatrix<T>* const _parent;
int _row;
public:
const_row(const DiagonalMatrix<T>* const parent, const int row)
: _parent(parent), _row(row) {}
const T& operator[](const int i) const;
};
friend class row;
friend class const_row;
public:
row operator[] (const int i);
const const_row operator[] (const int i) const;
// other stuff
};
And here are the relevant definitions:
template<class T>
typename DiagonalMatrix<T>::row DiagonalMatrix<T>::operator[](const int i)
{
if (i < 0 || i >= _size)
{
throw IndexOutOfBoundsException(i);
}
return DiagonalMatrix<T>::row(this, i);
}
template <class T>
T& DiagonalMatrix<T>::row::operator[](const int i)
{
if (i < 0 || i >= _parent->_size)
{
throw IndexOutOfBoundsException(i);
}
if (row == col)
{
return _parent->_data[row];
}
// TODO Add a real exception
throw "Cannot modify non-diagonal elements";
}
With similar definitions for the const versions, except the const operator[] returns a reference to the constant ZERO instead of throwing for non-diagonal elements.
So here is my problem: The non-const version is being called even when I don't need to modify anything. For example, this throws my error string:
DiagonalMatrix<double> diag(5);
// fill in the diagonal elements with some values
cout << diag[0][2] << endl;
However, if I remove the non-const versions of the operator, it behaves as expected and outputs a 0.
I've also tried something like:
T& at(const int row, const int col);
const T& at(const int row, const int col) const;
// in main:
cout << diag.at(0, 2) << endl;
But this has the same issue. So I have two questions:
1) Why does C++ choose the non-const version of the function over the const version even when I am not assigning to the result? Doesn't operator<< typically pass the right-hand object by const&?
2) How can I get around this? I'd rather not have separate get() and set() functions if I can help it.
1) Why does C++ choose the non-const version of the function over the const version even when I am not assigning to the result? Doesn't operator<< typically pass the right-hand object by const&?
It choose the non-const version because diag is not a const object.
2) How can I get around this? I'd rather not have separate get() and set() functions if I can help it.
You can define a const refrence to diag and use it to print values:
const DiagonalMatrix<double> &const_diag = diag;
cout << diag[0][2] << endl; // call const version
Or you define a function to print values and pass a const reference in:
void show_diag(const DiagonalMatrix<double> &diag)
{
cout << diag[0][2] << endl; // call const version
}
show_diag(diag);

() = 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).