Another point of confusion with this is illustrated below.
Given this code snippet:
const int M = 5;
const int N = 5;
matrix<float>
m( M, N);
triangular_matrix<
float, lower> lower (M, N);
// fill m with some values
lower = m; // copies from m, the values that
belong to the lower diagonal,
// so lower is the lower diagonal of m
cout << lower << endl; // prints lower diagonal matrix,
and for upper diagonal prints 0.
cout << lower( 4, 4) << endl; // throws
exception, since not indexing into lower diagonal
The print statement will show that the upper diagonal values are zero,
and then when you try to really access those, you find out that you
can't.
I haven't tried the other operations such as
m = lower + m
lower *= 2.0f;
but would expect those to work like the print statement, i.e. upper
diagonal elements are treated as zero.