Changing Elements with operator()()
The subscripting operator operator()(int,int) can be used to change elements in all matrix types. This can lead to runtime errors if you attempt to make changes that don't make sense. For example, consider the following program:
 
#include <rw/lapack/trdgmat.h>
 
int main()
{
RWTriDiagMat<double> A(5, 5);
A(4,0) = 7; // ERROR: Can't change this element
}
This program causes a runtime error because you can not change element (4, 0) of a tridiagonal matrix; it is defined to be 0.
Using operator()(int,int) to change elements can sometimes lead to side effects. For example, consider this program:
 
#include <rw/lapack/skewmat.h>
#include <iostream>
 
int main()
{
RWSkewMat<float> A(2, 2); // 1
A.zero(); // 2
A(0,1) = 1; // 3
A(1,0) = 1; // 4
std::cout << A << std::endl;
 
return 0;
}
At first it looks like the output of this program should be a matrix with 0s on the diagonal and 1s in the other two entries. However, the actual output is:
The problem is that the matrix must be skew symmetric at all times; it is, after all, a skew symmetric matrix! Line //3 does indeed set the top right element to 1, but in order to retain the skew symmetric shape of the matrix, it also sets the bottom left element to –1. Line //4 then sets the bottom left element to 1, but also sets the top right element to –1 as a side effect. Thus //3 is irrelevant; it changes the same two elements as //4!
At this point, you may ask just how these checks and side effects are implemented. After all, operator()(int,int) can't know whether it is used as a left side or a right side. The answer is that for some matrix types, operator()(int,int) returns an instance of a helper class. This class has a function that converts it to the appropriate type if a right-side value is needed. It also has an operator=() function that is called if the class is used as an lvalue; the function sets a matrix element to a value. This provides enough indirection for everything we need to do. For general and symmetric matrix shapes, this indirection is not necessary and a regular C++ reference is returned. Details of the helper classes are given in Chapter 9, Technical Notes.