Is it possible to const
-overload the function call operator operator()
so that:
- when the caller is on the left-hand side of an expression, the non-constant version is always called
- when the caller is on the right-hand side of the expression, the constant version is always called
?
I'm still learning C++ and spent hours yesterday scouring the Internet to figure out this one. ChatGPT and some other answers here suggested that this would be possible using a trick involving a helper or proxy class, but that seems to entail constructing such an object every time my operator()
is called. I'm wondering if this is possible in a less costly manner. I know that i can simply use a constant getter to solve this problem, but I'm curious to learn more about operator overloading.
Here's a toy program (hopefully) to clarify:
#include <iostream>
#include <vector>
// Implements a matrix. There are two arrays, a 'previous' and a 'current' one,
// to read the previous state from and to write the updated state into. Reading
// should always be from the 'previous' array and writing should always be to
// the 'current' array. The pointers to these arrays can be swapped.
class Matrix {
private:
// matrix dimensions
const int m_width;
const int m_height;
// arrays
std::vector<double> m_arr1;
std::vector<double> m_arr2;
// 'current' and 'previous' pointers to arrays
std::vector<double>* m_curr;
std::vector<double>* m_prev;
public:
Matrix(const int width, const int height)
:
m_width{width}, m_height{height},
m_arr1(width*height, 0.0), m_arr2(width*height, 0.0),
m_curr{&m_arr1}, m_prev{&m_arr2}
{}
// non-const version which I would always want to be called from the left-hand side
double& operator()(const int i, const int j) {
std::cout << "write to (" << i << ", " << j << ")" << std::endl;
return (*m_curr)[m_width*j + i];
}
// const version which I would always want to be called from the right-hand side
const double& operator()(const int i, const int j) const {
std::cout << "read from (" << i << ", " << j << ")" << std::endl;
return (*m_prev)[m_width*j + i];
}
void swap() {
std::cout << "swap" << std::endl;
std::vector<double>* temp{m_curr};
m_curr = m_prev;
m_prev = temp;
}
};
int main()
{
Matrix A{2, 2};
A(1, 0) = -1; // writes to 'current' array ('m_arr1')
A.swap(); // arrays are swapped
A(1, 0) = 3 + A(1, 0); // I wish this would write to 'current' array ('m_arr2') from 'previous' array ('m_arr1')
return 0;
}
The problem here is that since my 'Matrix' instances generally arent const
, the constant version doesn't get called. Is there a way to get the constant version called from the right-hand side without constructing helper or proxy objects? Thank you!