The mat_gen_dim notion of what "constant" means may not be intuitive. Here is a summary of what functions can be called from what matrix types:
var_matrix | var_matrix const | con_matrix | con_matrix const | |
---|---|---|---|---|
assign_form operator= | yes | no | yes | no |
get_vector count get_form get con_ref | yes | yes | yes | yes |
set var_ref linear_fill random_fill | yes | yes | no | no |
With the following definitions, where the hash mark represents suitable parameters:
var_matrix< # > mat_avar { # }; con_matrix< # > mat_acon { # }; var_matrix< # > mat_bvar { # }; con_matrix< # > mat_bcon { # };all four of the following assignments are legal:
mat_avar = mat_bvar; mat_acon = mat_bvar; mat_avar = mat_bcon; mat_acon = mat_bcon;The case of mat_avar = mat_bcon requires explanation. After assignment is complete, if mat_avar tries to change one of its components, cloning will take place and mat_bcon will not be affected.
As always, assignment to a const is prohibited:
var_matrix< # > const mat_avar { # }; con_matrix< # > const mat_acon { # }; mat_avar = /* anything */; // ILLEGAL mat_acon = /* anything */; // ILLEGAL
A non-const container can initialize a const container if the components are of precisely the same type, but a container of non-const objects cannot portably initialize a container of const objects, although it would seem to make sense:
var_matrix < double > vm1 {form {blt{1,4}}}; var_matrix < double > const vm2 {vm1}; // LEGAL var_matrix < double const > vm3 {vm1}; // ILLEGALAlong the same lines:
std::vector < double > sv1 {1.0,2.0,3.0}; std::vector < double > const sv2 (sv1); // LEGAL std::vector < double const > sv3 (sv1); // ILLEGAL
Within mat_gen_dim, the con_ prefix implies constancy of matrix components. In a sense, then, con_matrix<any_type> has a meaning similar to var_matrix<any_type const>. However, a limitation arises in that a mat_gen_dim matrix is ultimately stored as a std::vector, and the C++ Standard Library requires that vector components be assignable. (Some implementations do not report an error until, in the deeper workings of std::vector, a component assignment is actually attempted. Thus some programs with a std::vector<any_type const> may run, but not portably.)
Because any_type const is patently not assignable, something like var_matrix<any_type const> would not generally work without contortions of code, and mat_gen_dim does not attempt it as the program is already complicated enough.
In response to the requirement of assignability for the component type, the Standard Library provides std::vector<any_type>::const_iterator for the programmer who wants to iterate while ensuring the constancy of components. This is in place of converting a std::vector<any_type> to a std::vector<any_type const> and then creating a std::vector<any_type const>::iterator.
In short, con_matrix exists for the same reason as const_iterator. More, the family of lenses introduced in section 6 blurs the difference between matrices and iterators.
Here is a table of analogy among mat_gen_dim, the iterators of the Standard Library, and plain old pointers:
mat_gen_dim | Standard Library | plain old pointers | |||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
var_matrix:
| iterator:
| int * ip;
var_matrix const: |
iterator const: |
int * const ipc;
| con_matrix: |
const_iterator: |
int const * icp;
| con_matrix const: |
const_iterator const: |
int const * const icpc;
| |