Below is the snippet of code where the error lies, the line
a[i][j] = m[i][j] + w[i][j];
returns an error
lvalue required as left operand of assignment
I can't find an answer that applies to arrays, my Matrix is defined as follows:
Matrix::Matrix() {
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
coords[i][j] = 0.0f;
}
const Matrix operator+(const Matrix &m, const Matrix &w) {
Matrix a;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 4 ; j++)
a[i][j] = m[i][j] + w[i][j]; // <----- error
return a;
}
Here is the operator[]
How do I return by reference
const Vector Matrix::operator[](int i) const{
switch(i)
{
case 0: return Vector (coords[i][0], coords[i][1], coords[i][2]);
case 1: return Vector (coords[i][0], coords[i][1], coords[i][2]);
case 2: return Vector (coords[i][0], coords[i][1], coords[i][2]);
}
}
The error is actually "lvalue required as left operand of assignment".
It means that your a[i][j] is giving you a temporary object. This happens when you return from a function by value. A function call that returns by value is an rvalue expression, and you cannot use an rvalue expression as the left operand of an assignment. You need to change the implementation of operator[] on both the Matrix and the helper class that Matrix::operator[] returns so that they return by reference. A function call that returns by reference is an lvalue expression and will allow you to assign to it.
template <typename T>
Vector<T>& Matrix<T>::operator[](int index) { ... }
template <typename T>
T& Vector<T>::operator[](int index) { ... }
Of course, this makes sense. If your operator[]s didn't return by reference, how would assigning to the value returned by them have any effect on the contents of the Matrix?
In response to your edit:
You have a problem with the design of your class. The Matrix class appears to store a 3-by-3 array of floats called coords. However, when you use Matrix::operator[], it copies the values from a row of coords into a Vector object. They are copies. You then return that Vector by value, which copies the Vector and its contained values out of the function. Anything you do to that returned Vector will only affect that copy.
In addition to this, your switch statement is totally pointless. Every case is exactly the same. You just need to use i as the array indices and not switch on it.
Also, if you're going to allow people that call operator[] to modify the contents of your Matrix, then the operator[] function must not be const.
There are a few alternatives that will fix your problem. The first is to just return a float* instead and scrap your plan with Vector:
float* Matrix::operator[](int i) {
return coords[i];
}
That's a very simple solution but does involve passing a raw pointer around. The raw pointer can be used like an array, allowing you the syntax m[i][j].
You could do the same as the Eigen library and instead provide a operator() that takes two arguments, the row index and column index:
float& Matrix::operator()(int i, int j) {
return coords[i][j];
}
Note that the float is being returned by reference: float&. This means that is modifiable from outside the call to operator(). Here, you would index a row and column with m(i, j).
it means your [] operator returns a value without an address that cannot be used for assignment. Its straight forward.
What is Vector?
The problem probably starts with what Matrix::operator[]
returns. For the [][] syntax to work, it must return some
sort of proxy, to which the second [] can be applied, and it
will return a reference to the desired element in the matrix.
The usual way of doing this (at least for me) is to define
a "setter" and "getter" in Matrix:
void set( int i, int j, double new_value )
{
myData[ getIndex( i, j ) ] = new_value;
}
double get( int i, int j ) const
{
return myData[ getIndex( i, j ) ];
}
and then make use of two proxies (nested classes in Matrix):
class Proxy2D
{
Matrix* myOwner;
int myIndex1;
int myIndex2;
public:
Proxy2D( Matrix& owner, int index1, int index2 )
: myOwner( &owner )
, myIndex1( index1 )
, myIndex2( index2 )
{
}
void operator=( double new_value ) const
{
myOwner->set( myIndex1, myIndex2, new_value ):
}
operator double() const
{
return myOwner->get( myIndex1, myIndex2 );
}
};
class Proxy1D
{
Matrix* myOwner;
int myIndex;
public:
Proxy1D( Matrix& owner, int index )
: myOwner( &owner )
, myIndex( index )
{
}
Proxy2D operator[]( int index2 ) const
{
return Proxy2D( *myOwner, myIndex, index2 );
}
};
Proxy1D operator[]( int index1 )
{
return Proxy1D( *this, index1 );
}
In practice, you'll want const variants as well, to be returned
by operator[]( int index1 ) const. And of course,
ConstProxy2D won't need the overload for operator=; the
implicit conversion is sufficient.
And in case it isn't obvious, Matrix::getIndex does the bounds
checking, and then calculates the actual index in the underlying
std::vector<double> which contains the data.
Since you return a newly constructed Vector object to represent a column (or row, doesn't really matter), this Vector is responsible to update an entry in the original Matrix instance, which is a little bit tricky but can easily be solved:
You have to implement another VectorRef class which doesn't represent a vector by value but by reference and can thus be used to access the components as lvalues. This means, that it doesn't contain the numbers as values but as reference and takes these references in its constructor. To keep things simple, you can use a pointer which points to the first component (followed by the other components):
class VectorRef {
float *coords;
public:
VectorRef(float *coords) : coords(coords) {}
float & operator[](int i) { return coords[i]; }
};
Then, construct such a "reference object" in the operator[] of the matrix:
VectorRef Matrix::operator[](int i) {
return VectorRef (coords[i]);
}
To use the VectorRef also as a Vector, provide a conversion operator:
// (within VectorRef:)
operator Vector() const { return Vector(coords[0], coords[1], coords[2]); }
This should make things seemless.
Alternatively, if you always access the elements within a matrix and not columns as a whole, just return the column pointer directly in the operator[] of the matrix:
float * Matrix::operator[](int i) {
return coords[i];
}
When writing mat[x][y], this will first access the float pointer with mat[x] and then accesses the y-th element of that column, which is an lvalue.
Related
Consider the task of writing an indexable class which automatically synchronizes its state with some external data-store (e.g. a file). In order to do this the class would need to be made aware of changes to the indexed value which might occur. Unfortunately the usual approach to overloading operator[] does not allow for this, for example...
Type& operator[](int index)
{
assert(index >=0 && index < size);
return state[index];
}
I there any way to distinguish between a value being accessed and a value being modified?
Type a = myIndexable[2]; //Access
myIndexable[3] = a; //Modification
Both of these cases occur after the function has returned. Is there some other approach to overloading operator[] which would perhaps make more sense?
From the operator[] you can only really tell access.
Even if the external entity uses the non cost version this does not mean that a write will take place rather that it could take place.
As such What you need to do is return an object that can detect modification.
The best way to do this is to wrap the object with a class that overrides the operator=. This wrapper can then inform the store when the object has been updated. You would also want to override the operator Type (cast) so that a const version of the object can be retrieved for read accesses.
Then we could do something like this:
class WriteCheck;
class Store
{
public:
Type const& operator[](int index) const
{
return state[index];
}
WriteCheck operator[](int index);
void stateUpdate(int index)
{
// Called when a particular index has been updated.
}
// Stuff
};
class WriteCheck
{
Store& store;
Type& object;
int index;
public: WriteCheck(Store& s, Type& o, int i): store(s), object(o), index(i) {}
// When assignment is done assign
// Then inform the store.
WriteCheck& operator=(Type const& rhs)
{
object = rhs;
store.stateUpdate(index);
}
// Still allow the base object to be read
// From within this wrapper.
operator Type const&()
{
return object;
}
};
WriteCheck Store::operator[](int index)
{
return WriteCheck(*this, state[index], index);
}
An simpler alternative is:
Rather than provide the operator[] you provide a specific set method on the store object and only provide read access through the operator[]
You can have (the non-const) operator[] return a proxy object that keeps a reference or pointer to the container, and in which operator= signals the container of the update.
(The idea of using const vs non-const operator[] is a red herring... you may know that you've just given away non-const access to the object, but you don't know if that access is still being used for a read or a write, when that write completes, or have any mechanism for updating the container thereafter.)
Another elegant (IMHO) solution...
Actually it is based on the fact that the const overload is called only when used on const object.
Lets first create two [] overloads - as it is required, but using different locations:
Type& operator[](int index)
{
assert(index >=0 && index < size);
return stateWrite[index];
}
const Type& operator[](int index) const
{
assert(index >=0 && index < size);
return stateRead[index];
}
Now you should create a shadow reference of your object when you need to "read" it as follows:
const Indexable& myIndexableRead = myIndexable; // create the shadow
Type a = myIndexableRead[2]; //Access
myIndexable[3] = a; //Modification
Creating this shadow declaration does not actually create anything in the memory. It just creates another name for your object with "const" access. It is all resolved at the compilation stage (including usage of const overload) and does not affect anything in runtime - neither memory nor performance.
And the bottom line - it is much more elegant (IMHO) than creating any assignment proxies, etc. I must state that the statement "From the operator[] you can only really tell access" is incorrect. According to the C++ Standard, returning dynamically allocatted object or global variable by reference is ultimate way to allow its direct modification, including [] overload case.
Following code has been tested:
#include <iostream>
using namespace std;
class SafeIntArray {
int* numbers;
int size;
static const int externalValue = 50;
public:
SafeIntArray( unsigned int size = 20 ) {
this->size = size;
numbers = new int[size];
}
~SafeIntArray() {
delete[] numbers;
}
const int& operator[]( const unsigned int i ) const {
if ( i < size )
return numbers[i];
else
return externalValue;
}
int& operator[]( const unsigned int i ) {
if ( i < size )
return numbers[i];
else
return *numbers;
}
unsigned int getSize() { return size; }
};
int main() {
SafeIntArray arr;
const SafeIntArray& arr_0 = arr;
int size = arr.getSize();
for ( int i = 0; i <= size ; i++ )
arr[i] = i;
for ( int i = 0; i <= size ; i++ ) {
cout << arr_0[i] << ' ';
}
cout << endl;
return 0;
}
And the results are:
20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 50
Return a proxy object which will have:
operator=(Type const &) overloaded for writes
operator Type() for reads
in the access example you give you can get a distinction by using a const version:
const Type& operator [] ( int index ) const;
on a sidenote, using size_t as index gets rid of the need for checking if index >= 0
#include "stdafx.h"
#include <iostream>
template<typename T>
class MyVector
{
T* _Elem; // a pointer to the elements
int _Size; // the size
public:
// constructor
MyVector(int _size):_Size(_size), _Elem(new T[_size])
{
// Initialize the elemets
for( int i=0; i< _size; ++i )
_Elem[i] = 0.0;
}
// destructor to cleanup the mess
~MyVector(){ delete []_Elem; }
public:
// the size of MyVector
int Size() const
{
return _Size;
}
// overload subscript operator
T& operator[]( int i )
{
return _Elem[i];
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyVector<int> vec(10);
vec[0] =10;
vec[1] =20;
vec[2] =30;
vec[3] =40;
vec[4] =50;
std::cout<<"Print vector Element "<<std::endl;
for (int i = 0; i < vec.Size(); i++)
{
std::cout<<"Vec["<<i<<"] = "<<vec[i]<<std::endl;
}
return 0;
}
I've got class with overloaded [] and I need to make it to recognize, when I try to set the values to the array. I assume, that I'll have to overload the operator =, nevertheless I don't know, how shall that whole stuff look like. Part of my code:
class Matrix {
public:
Matrix(int x, int y);
~Matrix(void);
Matrix& operator =(const Matrix &matrix); //ok...this is probably wrong...
class Proxy {
public:
Proxy(double* _array) : _array(_array) {
}
double &operator[](int index) const {
return _array[index];
}
private:
double* _array;
};
Proxy operator[](int index) const {
return Proxy(_arrayofarrays[index]);
}
Proxy operator[](int index) {
return Proxy(_arrayofarrays[index]);
}
int x, y;
double** _arrayofarrays;
};
So I just need to be able to recognize when I try to set Matrix matrix(3,3); matrix[0][0]=1;
Everything else works allright, so I assumed that it's not needed to paste the whole code
It looks like you want something which is not directly possible: operator[][].
You can emulate the behavior of this by using an intermediate class:
Since a Matrix class is typically indexed as [rows][columns], you can
have the first operator method return the corresponding Row object.
The row class can than overload the operator[] and return the corresponding
element.
Row& Matrix::operator[](int r);
double& Row::operator[](int c);
Now when you create your matrix object, you can index it as expected:
Matrix matrix(3,3);
matrix[0][0] = 1;
The last line is then equivalent to calling:
matrix.operator[](0).operator[](0) = 1;
To check for out-of-bounds indices, store the matrix sizes:
Proxy operator[](int index) {
assert(index < num_rows);
return Proxy(_arrayofarrays[index]);
}
double &operator[](int index) const {
assert(index < num_cols);
return _array[index];
}
As Aldo suggeested, Proxy can be passed the array length value in it's constructor:
Proxy(double* _array, int _length) : _array(_array), num_cols(_length){
}
As a general rule of thumb, if you're passing a raw array to a function, you will almost always want to pass the length of that array as well.
Your Proxy::operator[] overload is returning a double&. This double& is the object that will eventually be assigned to by client code, and you can't intercept that (at least not easily). Probably what you need to do is to check the index parameter in your operator[] overloads, and throw your own exception there rather than passing that index along to your internal arrays.
I am writing a matrix class in c++ and trying to overload some operator like = and >> and << etc.
I was unable to overload operator [][] for matrix class.
if i have an object of class matrix like M1 then i can use this way for giving value to each element:
M1[1][2]=5;
OR
int X;
X=M1[4][5];
Just overload operator[] and make it return a pointer to the respective row or column of the matrix. Since pointers support subscripting by [], access by the 'double-square' notation [][] is possible then.
You can also overload operator() with two arguments.
There is no operator[][] in C++. You have to return a helper object and then overload operator[] for that too, to have this kind of access.
You could overload operator[]. So if you would like to use matrix that way, you should make matrix as array of vectors.
class Matrix
{
...
Vector & operator[]( int index );
...
};
and
class Vector
{
...
double & operator[]( int index );
...
};
Finally:
Matrix m;
...
double value = m[i][j];
...
there is no operator[][], you can implement operator[] to return a reference to the row/column object, in which you can implement the operator[] to return you the cell reference.
You can do something like the following to avoid all that hassle..
struct loc
{
int x;
int y;
};
then in your operator[] overload, accept a loc, something like
T& operator[](loc const& cLoc)
{
// now you have x/y you can return the object there.
}
To call, you can simply do something like:
matrix[loc(2,3)] = 5;
Actually, I did just that in my own matrix class a few years ago. In this case, I defined a matrix template class that contained the snippet, below.
I was then able to iterate and assign as follows:
for(size_t k=1; k<n; ++k) {
minor[p][k-1]=major[j][k];
}
I hope this helps.
// //////////////////////////////////////////////////////////////////////////////
// list is internal vector representation of n x m matrix
T* list;
// Proxy object used to provide the column operator
template < typename T >
class OperatorBracketHelper
{
Matrix < T > & parent ;
size_t firstIndex ;
public :
OperatorBracketHelper ( Matrix < T > & Parent , size_t FirstIndex ) :
parent ( Parent ), firstIndex ( FirstIndex ) {}
// method called for column operator
T & operator []( size_t SecondIndex )
{
// Call the parent GetElement method which will actually retrieve the element
return parent.GetElement ( firstIndex , SecondIndex );
}
};
// method called for row operator
OperatorBracketHelper < T > operator []( size_t FirstIndex )
{
// Return a proxy object that "knows" to which container it has to ask the element
// and which is the first index (specified in this call)
return OperatorBracketHelper < T >(* this , FirstIndex );
}
T & GetElement ( size_t FirstIndex , size_t SecondIndex )
{
return list[FirstIndex*cols+SecondIndex];
}
I am exactly working on a matrix class and I decided to first create an Array class which has a dynamic 2-D array. So, well just as you, I confronted this obstacle that how I can overload two square brackets. How I approached this case is very simple; I overloaded the square brackets operator twice as member functions. First, I overloaded [] so as to return a pointer pointing to the desired row, so to speak, and then the following member function (i.e. again operator [] overloaded) returns a lvalue of the same type as the array's elements.
However, note that the index you inter to invoke the former overloaded operator [] must be saved somewhere so that you may use it in the latter overloaded operator []. For this reason I simply added a new member of the type int to the class Array (which I've named it "test" in my code below).
class Array {
private:
double **ptr; int test;
... /* the rest of the members includes the number of rows and columns */
public:
Array(int=3,int=3); // Constructor
Array(Array &); // Copy Constructor
~Array(); // Destructor
void get_array();
void show_array();
double* operator[] (int);
double operator[] (short int);
...
};
...
double* Array::operator[] (int a) {
test = a;
double* p = ptr[test];
return p;
}
double Array::operator[] (short int b) {
return ((*this)[test][b]);
}
Therefor, as an example, in main I can simply write:
int main(){
Array example;
cout << example[1][2];
}
I hope this would help you.
You can't overload [][] as such, since there isn't such an
operator. You can overload [] to return something which also
has an [] defined on it (a proxy); in the simplest case,
something like a double* will work, but it's usually better,
although a bit more work, to use a full class. (Place to add
bounds checking, for example.)
Alternatively, you can overload (x,y). Depending on who you
ask, one format or the other is "better". (In fact, it's
strictly a question of style.)
Template matrix class
template <uint8_t rows, uint8_t cols, typename T>
class MatrixMxN {
public:
T* operator[](uint8_t f_row) {
return &m_val[f_row * cols];
}
protected:
T m_val[rows*cols];
};
and here is object of matrix with 3 row, 4 column and integer type.
MatrixMxN<3, 4, int32_t> M;
M[2][3] = 10;
std::cout << M[2][3] << std::endl;
Consider the task of writing an indexable class which automatically synchronizes its state with some external data-store (e.g. a file). In order to do this the class would need to be made aware of changes to the indexed value which might occur. Unfortunately the usual approach to overloading operator[] does not allow for this, for example...
Type& operator[](int index)
{
assert(index >=0 && index < size);
return state[index];
}
I there any way to distinguish between a value being accessed and a value being modified?
Type a = myIndexable[2]; //Access
myIndexable[3] = a; //Modification
Both of these cases occur after the function has returned. Is there some other approach to overloading operator[] which would perhaps make more sense?
From the operator[] you can only really tell access.
Even if the external entity uses the non cost version this does not mean that a write will take place rather that it could take place.
As such What you need to do is return an object that can detect modification.
The best way to do this is to wrap the object with a class that overrides the operator=. This wrapper can then inform the store when the object has been updated. You would also want to override the operator Type (cast) so that a const version of the object can be retrieved for read accesses.
Then we could do something like this:
class WriteCheck;
class Store
{
public:
Type const& operator[](int index) const
{
return state[index];
}
WriteCheck operator[](int index);
void stateUpdate(int index)
{
// Called when a particular index has been updated.
}
// Stuff
};
class WriteCheck
{
Store& store;
Type& object;
int index;
public: WriteCheck(Store& s, Type& o, int i): store(s), object(o), index(i) {}
// When assignment is done assign
// Then inform the store.
WriteCheck& operator=(Type const& rhs)
{
object = rhs;
store.stateUpdate(index);
}
// Still allow the base object to be read
// From within this wrapper.
operator Type const&()
{
return object;
}
};
WriteCheck Store::operator[](int index)
{
return WriteCheck(*this, state[index], index);
}
An simpler alternative is:
Rather than provide the operator[] you provide a specific set method on the store object and only provide read access through the operator[]
You can have (the non-const) operator[] return a proxy object that keeps a reference or pointer to the container, and in which operator= signals the container of the update.
(The idea of using const vs non-const operator[] is a red herring... you may know that you've just given away non-const access to the object, but you don't know if that access is still being used for a read or a write, when that write completes, or have any mechanism for updating the container thereafter.)
Another elegant (IMHO) solution...
Actually it is based on the fact that the const overload is called only when used on const object.
Lets first create two [] overloads - as it is required, but using different locations:
Type& operator[](int index)
{
assert(index >=0 && index < size);
return stateWrite[index];
}
const Type& operator[](int index) const
{
assert(index >=0 && index < size);
return stateRead[index];
}
Now you should create a shadow reference of your object when you need to "read" it as follows:
const Indexable& myIndexableRead = myIndexable; // create the shadow
Type a = myIndexableRead[2]; //Access
myIndexable[3] = a; //Modification
Creating this shadow declaration does not actually create anything in the memory. It just creates another name for your object with "const" access. It is all resolved at the compilation stage (including usage of const overload) and does not affect anything in runtime - neither memory nor performance.
And the bottom line - it is much more elegant (IMHO) than creating any assignment proxies, etc. I must state that the statement "From the operator[] you can only really tell access" is incorrect. According to the C++ Standard, returning dynamically allocatted object or global variable by reference is ultimate way to allow its direct modification, including [] overload case.
Following code has been tested:
#include <iostream>
using namespace std;
class SafeIntArray {
int* numbers;
int size;
static const int externalValue = 50;
public:
SafeIntArray( unsigned int size = 20 ) {
this->size = size;
numbers = new int[size];
}
~SafeIntArray() {
delete[] numbers;
}
const int& operator[]( const unsigned int i ) const {
if ( i < size )
return numbers[i];
else
return externalValue;
}
int& operator[]( const unsigned int i ) {
if ( i < size )
return numbers[i];
else
return *numbers;
}
unsigned int getSize() { return size; }
};
int main() {
SafeIntArray arr;
const SafeIntArray& arr_0 = arr;
int size = arr.getSize();
for ( int i = 0; i <= size ; i++ )
arr[i] = i;
for ( int i = 0; i <= size ; i++ ) {
cout << arr_0[i] << ' ';
}
cout << endl;
return 0;
}
And the results are:
20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 50
Return a proxy object which will have:
operator=(Type const &) overloaded for writes
operator Type() for reads
in the access example you give you can get a distinction by using a const version:
const Type& operator [] ( int index ) const;
on a sidenote, using size_t as index gets rid of the need for checking if index >= 0
#include "stdafx.h"
#include <iostream>
template<typename T>
class MyVector
{
T* _Elem; // a pointer to the elements
int _Size; // the size
public:
// constructor
MyVector(int _size):_Size(_size), _Elem(new T[_size])
{
// Initialize the elemets
for( int i=0; i< _size; ++i )
_Elem[i] = 0.0;
}
// destructor to cleanup the mess
~MyVector(){ delete []_Elem; }
public:
// the size of MyVector
int Size() const
{
return _Size;
}
// overload subscript operator
T& operator[]( int i )
{
return _Elem[i];
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyVector<int> vec(10);
vec[0] =10;
vec[1] =20;
vec[2] =30;
vec[3] =40;
vec[4] =50;
std::cout<<"Print vector Element "<<std::endl;
for (int i = 0; i < vec.Size(); i++)
{
std::cout<<"Vec["<<i<<"] = "<<vec[i]<<std::endl;
}
return 0;
}
I'm using a 2D matrix in one of my projects. It's something like it is suggested at C++ FAQ Lite.
The neat thing is that you can use it like this:
int main()
{
Matrix m(10,10);
m(5,8) = 106.15;
std::cout << m(5,8);
...
}
Now, I have a graph composed of vertices and each vertex has a public (just for simplicity of the example) pointer to 2D matrix like above. Now I do have a pretty ugly syntax to access it.
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
Probably I'm missing some syntactic sugar here due to my inexperience with operator overloading. Is there a better solution?
Consider using references instead of pointers (provided, it can't be null and you can initialize in the constructor).
Consider making a getter or an instance of a matrix wrapper class for a vertex that returns a reference to 2D matrix (provided, it can't be null).
sampleVertex.some2DTable()(0,0) = 0;
sampleVertex.some2DTableWrap(0,0) = 0;
However, to me it sounds like a non-issue to justify going through all the trouble.
If you have a pointer to a Matrix, e.g. as a function parameter that you can't make a reference (legacy code, e.g.), you can still make a reference to it (pseudo code):
struct Matrix {
void operator () (int u, int v) {
}
};
int main () {
Matrix *m;
Matrix &r = *m;
r (1,1);
}
You're basically limited to (*sampleVertex.some2DTable)(0,0). Of course, if you don't need reseating, why not store the actual values in the matrix instead?
Alternatively, make the pointer private and make an accessor (note: the following examples assume a matrix of EntryTypes):
Matrix& Vertex::GetTableRef()
{
return *some2DTable;
}
// or
Matrix::EntryType& Vertex::GetTableEntry(int row, int col)
{
return (*some2DTable)(row,col);
}
// way later...
myVertex.GetTableRef()(0,0) = 0;
// or...
myVertex.GetTableEntry(0,0) = 0;
Or, just define an inline function to do this for you if you can't change the class Vertex:
// in some header file
inline Matrix& GetTableRef(Vertex& v)
{
return *v.some2DTable;
}
// or you could do this
inline Matrix::EntryType& GetTableEntry(Vertex& v, int row, int col)
{
return (*v.some2DTable)(row, col);
}
// later...
GetTableRef(myVertex)(0, 0) = 0;
// or
GetTableEntry(myVertex, 0, 0) = 0;
Finally, don't forget that you don't have to use operator overloading. STL collections implement an at() member function, which is checked, as opposed to operator[] which is unchecked. If you don't mind the overhead of bounds checking, or if you just want to be nonstandard, you could implement at() and then just call myVertex.some2DTable->at(0,0), saving a bit of a syntactic headache altogether.
There is no C++ syntactic sugar that will ease the pain of what you describe:
(*sampleVertex.some2DTable)(0,0) = 0; //bad
sampleVertex.some2DTable->operator()(0,0) = 0; //even worse...
In this situation, I would either have the graph return a reference instead of a pointer, or have the matrix define a function which calls the operator():
inline matrixType &Matrix::get( int x, int y ){ return operator()(x,y); }
Then, the syntax isn't quite as ugly for the vertex example:
sampleVertex.some2DTable->get(0,0) = 0;
I would add a function that returns you a ref like rlbond recommends. For a quick fix or if you don't have control over the source of it, i would go with this:
sampleVertex.some2DTable[0](0,0) = 0; // more readable
That's actually equivalent, because the following holds if a is a pointer to a defined class:
*a == *(a + 0) == a[0]
See this long discussion on comp.lang.c++ about that same problem with good answers.
This is the best way without changing your code:
//some2DTable is a pointer to a matrix
(*sampleVertex.some2DTable)(0,0)
You could also instead make some2DTable a reference to a matrix instead of a pointer to a matrix. Then you would have simplified syntax as in your first code sniplet.
//some2DTable is a reference to a matrix instead of a pointer to a matrix
sampleVertex.some2DTable(0,0)
Or you could keep some2DTable a pointer to a reference and simply store a reference variable to it and use that in the context of your code block.
I'd change the way you get hold of "sampleVertex.some2DTable" so it returns a reference.
Either that or create the reference yourself:
Matrix& m = *sampleVertex.some2DTable;
m(1,2) = 3;
I don't know if it's worth the trouble, but you could do:
class MatrixAccessor {
private:
Matrix2D* m_Matrix;
public:
MatrixAccessor(Matrix2D* matrix) : m_matrix(matrix) { }
double& operator()(int i, int j) const { return (*m_Matrix)(i,j); }
Matrix2D* operator->() const { return m_Matrix; }
void operator=(Matrix2D* matrix) { m_Matrix = matrix; }
};
Provided the original operator() returns a reference (as it is in many matrix classes).
Then you provide that MatrixAccessor in your vertex class:
class Vertex {
Matrix2D* myMatrix;
public:
MatrixAccessor matrix;
Vertex(Matrix2D *theMatrix) : myMatrix(theMatrix), matrix(theMatrix) { }
};
Then you can write:
Vertex v;
v.matrix(1,0) = 13;
v.matrix->SomeOtherMatrixOperation();
EDIT
I added const keywords (thanks to #phresnel for bringing up the topic) in order to make the solution semantically equivalent to a solution only presenting a public Matrix2D-pointer.
An advantage of this solution is that constness could be transferred to the matrix object by adding two non-const versions of the operator()() and operator->() (i.e. the matrix cannot be modified on const vertices) and changing the const ones to return a const double& and const Matrix2D* respectively.
That would not be possible when using a public pointer to the matrix object.
You could implement Matrix::operator (int,int) by calling a member function and use that one directly when dealing with pointers.
class Matrix
{
public:
float ElementAt( int i, int j ) const { /*implement me*/ }
float operator() ( int i, int j ) const { return ElementAt( i, j ); }
...
};
void Foo(const Matix* const p)
{
float value = p->ElementAt( i, j );
...
}
void Bar(const Matrix& m)
{
float value = m(i,j);
}