Getting error "Expression is not assignable "

I have a matrix class and I'm trying to add a number in a spot in my matrix , but its giving me the error "Expression is not assignable" .

I was told by a colleague that I wasn't initialising the object with the constructor , so i done it his way and still didn't work ..
Any Help ?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

#ifndef MATRIX_H
#define MATRIX_H

#include "vector.h"

class Matrix
{ // class Matrix
    public: // makes life easier
    float coords[3][3]; // treat each row as a vector

    Matrix(); // default constructor
    Matrix(float Coords[3][3]);
    ~Matrix();

    const Matrix Identity()        const; // returns identity matrix
    const Vector operator[](int i) const ; // returns a row as a vector
    const Vector column(int j)     const ; // returns a column as vector
}; // class Matrix

std::ostream &operator<< (std::ostream & ostr, Matrix m);
// C++ print routine

/**
 * Matrix Operations
 */
const Point  operator* (const Matrix &m, const Point  &p);
const Vector operator* (const Matrix &m, const Vector &v);
const Matrix operator* (const Matrix &m, const Matrix &w);
const Matrix operator+ (const Matrix &m, const Matrix &w);
const Matrix operator- (const Matrix &m, const Matrix &w);
#endif


  #include "matrix.h"

Matrix::Matrix(){
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            coords[i][j] = 0.0f; // set to something reliable
}

Matrix::Matrix(float Coords[3][3]){
    for(int i = 0; i < 3; i++)
        for(int j = 0; j < 3; j++)
            coords[i][j] = Coords[i][j];
}

Matrix::~Matrix()
{}

const Matrix Matrix::Identity() const{
    float ident[3][3] = { {1.0, 0.0, 0.0},
			  {0.0, 1.0, 0.0},
			  {0.0, 0.0, 1.0} };
    return Matrix(ident);
}

const Vector Matrix::operator[](int i) const{
  return Vector(coords[i][0], coords[i][1], coords[i][2]);
}

const Vector Matrix::column(int j) const {
    return Vector(coords[0][j], coords[1][j], coords[2][j]);
}

std::ostream &operator<< (std::ostream & ostr, Matrix m)
{ // print operator
    for (int i = 0; i < 3; i++){
        ostr << m[i] << std::endl;
    }
    return ostr;
} // print operator


const Point operator* (const Matrix &m, const Point &p)
{ // operator*
   int a [3] ;

   for (int i = 0 ; i<3;i++){
        for (int j =0;j<3;j++){
            a[i] += m[i][j] * p[j];
       }
   }

    return Point(a[0], a[1], a[2] );
} // operator*

const Vector operator* (const Matrix &m, const Vector &v)
{ // operator*

    int a [3] ;
    for (int i = 0 ; i<3;i++){
        a[i] = m[i].dot(v);
    }
    return Vector( a[0], a[1],a[2] );
} // operator*

const Matrix operator* (const Matrix &m, const Matrix &w) {

    Matrix a ;
//   a[1][2] = 2; Error occurs here
    std::cout << a[1][2] << std::endl;
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++)
        {
            a[i][j] = 0;          // Error occurs here
            for (int k = 0; k < 3; k++){
                a[i][j] += m[i][k] * w[k][j]; //Error occurs here
        }}
    }

    return a;
}

const Matrix operator+(const Matrix &m, const Matrix &w) {
    Matrix a;
    for (int i = 0 ; i<3;i++){
         for (int j =0;j<3;j++){
             a[i][j] = m[i][j] + w[i][j];   // Error occurs here
        }
    }
    return a;
}

const Matrix operator-(const Matrix &m, const Matrix &w) {
    Matrix a;
    for (int i = 0 ; i<3;i++){
         for (int j =0;j<3;j++){
             a[i][j] = m[i][j] - w[i][j];     // Error occurs here
        }
    }
    return a;
}





Last edited on
What does a[i][j] returns? I see a[i] would return a constant Vector, so I doubt that result of another [] application would be mutable.
Not sure what "Vector" is, but assuming it has an operator[] that returns a reference to the object at that index.

For the semantics to work as you expect, you need to return a reference to a Vector, otherwise you will not be changing the original data as you intended. This implies you need some sort of Vector in your internal data that you can return a reference to.

Whatever you're returning cannot be const, otherwise you can't modify it.

The function itself cannot be const since it's going to modify members ( you could exploit overloading to provide a const and non const version of your operator)

You may be better off using std::vector, i.e. vector<vector<double>> coord; Maybe derive your own class from std::vector and enforce the 3x3 rule. The upshot with datat as a vector of vectors is that you could have vector<float> &operator[](int); Much easier/safer than trying to return pointers to the internal data
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#include "vector.h"
#include "math.h"

Vector::Vector(){
    x = y = z = 0.0f;
}

Vector::Vector(float X,float Y, float Z){
    x = X; y = Y; z = Z;
}

Vector::~Vector()
{}

float Vector::operator [ ](int i) const{

    switch(i){
    case 0: return x;
    case 1:return y;
    case 2: return z;
    default :
         std::cout << "ERROR ....";
         return x;
    }
    //return something
        return x;
}

float Vector::length() const{


    return sqrt(x*x + y*y + z*z);
}

float Vector::dot(const Vector &v) const {

    return (x*v.x + y*v.y + z*v.z);
}

const Vector Vector::norm() const{

    return Vector( 0.0,0.0,0.0 );
}

const Vector Vector::cross(const Vector &v) const {

    return Vector( (y*v.z) - (z*v.y) ,((z*v.x)-(x*v.z)),((x*v.y)-(y*v.x)) );
}

// C++ print routine
std::ostream & operator<< (std::ostream & ostr, Vector v){
    ostr << "(" << v.x << ", " << v.y << ", " << v.z << ")";
    return ostr;
}

const Vector operator -(const Vector &v){

    return Vector( -v.x,-v.y,-v.z );
}

//Addition
const Point operator+ (const Point &p, const Vector &v){

    return Point((p.x + v.x),(p.y + v.y),(p.z + v.z));
}

const Vector operator+ (const Vector &v, const Vector &w){


    return Vector( v.x+w.y,v.y+w.y,v.z+w.z );
}
// Subtraction
const Point operator- (Point p, Vector v){

    return Point( p.x-v.x,p.y-v.y,p.z-v.z );
}


const Vector operator- (Vector v, Vector w){

    return Vector( v.x-w.x,v.y-w.y,w.z-w.z );
}

const Vector operator- (const Point &tail, const Point &head){

    return Vector( tail.x -head.x ,tail.y - head.y,tail.z -head.z );
}

// Scalar Multiplication
const Vector operator* (float s, const Vector &v){

    return Vector( s * v.x,s * v.y,s * v.z );
}

const Vector operator* (const Vector &v, float s){

    return Vector( v.x*s,v.y*s,v.z*s );
}




Heres my Vector.cpp file
float Vector::operator [ ](int i) const{ You are returning by value — unnamed temporary which cannot be assigned to (as it is a prvalue).

Maybe derive your own class from std::vector
Do not do that. std::vector is not created for inheriting from it. It does not have virtual functions, it does not have virtual destructor, it is not suited for it at all. Even if you inherit from it privately, you will not get anything useful from it.

As tipaye said, you need to return a reference or proxy for original value. You can either store array of Vectors inside Matrix and return references for Vector/value, or store array in Matrix (like now) and return Vector by value, but make Vector contain references to original values.

In which case, I suggest using Vector coords[3]; instead of float coords[3][3];in class Matrix
Or, copying how you implemented Vecto, Vector x; Vector y; Vector z;
Also, use double instead of float, float is a bit old-fashioned these days.

To preserve the usual semantics of[], you'd need:
1
2
3
4
5
6
7
8
9
10
11
12
13
float &Vector::operator [ ](int i) {

    switch(i){
    case 0: return x;
    case 1:return y;
    case 2: return z;
    default :
         std::cout << "ERROR ....";
         return x;
    }
    //return something
        return x;
}

notice it's returning a reference not a value, and the function is not const

1
2
3
4
5
6
Vector &Matrix::operator[](int i) {
if (i <3 && >= 0)
  return Vector(i);
else
  ;// handle problems
}


Or if you used 3 Vectors, then exactly like inVector operator[](int):
1
2
3
4
5
6
7
8
9
10
11
12
13
Vector &Matrix::operator[](int i) {

    switch(i){
    case 0: return x;
    case 1:return y;
    case 2: return z;
    default :
         std::cout << "ERROR ....";
         return x;
    }
    //return something
        return x;
}

Also, I think that "return x" in the default case is redundant.
If you turn the operators into methods then you'll have access to the private members of Matrix and the problem can go away. In other words, instead of:
const Matrix operator* (const Matrix &m, const Matrix &w);
do this:
1
2
3
4
5
6
class Matrix
{ // class Matrix
    public: // makes life easier
    ...
    const Matrix operator* (const Matrix &rhs); // rhs means "right hand side"
};

Then the implementation is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const Matrix Matrix::operator* (const Matrix &rhs) {

    Matrix a;
    a.coords[1][2] = 2;
    std::cout << a[1][2] << std::endl;
    for (int i = 0; i < 3; i++){
        for (int j = 0; j < 3; j++) {
            a.coords[i][j] = 0;          // Error occurs here
            for (int k = 0; k < 3; k++){
                a.coords[i][j] += coords[i][k] * rhs.coords[k][j];
            }
        }
    }

    return a;
}


One more thing. In operator* (const Matrix &m, const Point &p), you need to initialize a[3] to zeros.
Topic archived. No new replies allowed.