Content

Const-Correctness

In FLENS matrix/vector views act and behave like references in C++ just for matrix/vector parts instead of scalar values:

Pure C++ Types

Analogous Role of FLENS Types

int

DenseVector<Array<double> >

int &

DenseVector<ArrayView<double> >

const int &

const DenseVector<ConstArrayView<double> >

Views in FLENS

The beauty of this FLENS approach is that you can write functions that take any kind of DenseVector:

  template <typename VX>                                           
     void                                                          
     dummy(const DenseVector<VX> &x);                              

or

  template <typename VX>                                           
     void                                                          
     dummy(DenseVector<VX> &x);                                    

Using traits you also can implement functions that accept non-const rvalues

  template <typename VX>                                           
     typename RestrictTo<IsDenseVector<VX>::Type,                  
              void>::Type                                          
     dummy(VX &&x);   a                                            

the latter is necessary in an expression like

  dummy(x(_(3,7));                                                 

where the view is a temporary object.

Design Flaw in MTL4

If you want to provide views you really need different types for const and non-const views. Till the moment of this writing (2012/09/01) the MTL4 guys think there was a 'simpler way'. As a consequence the const attribute is only decoration. In a large application this can lead to bugs that are hard to find. But even worse, even the compiler can not trace that you are violating const correctness. So for optimizations the compiler might rely on the const attribute. That means bugs will depend on your level of optimization (i.e. in debug mode you application works find but crashes in non-debug mode).

MTL4 Example

#include <iostream>
#include <boost/numeric/mtl/mtl.hpp>

using namespace mtl; using mtl::iall;

//
// we feed the beast with a const reference
//
void
beast(const dense2D<double> &A)
{
    dense2D<double>   B = sub_matrix(A, 0505);
    B[1][1] = 666;
}

int main(intchar**)
{
    using namespace mtl; using mtl::iall;

    const int         m = 5, n = 5;
    dense2D<double>   A(n, n);

    for (int i=0; i<m; ++i) {
        for (int j=0; j<n; ++j) {
            A[i][j] = i+j;
        }
    }

    std::cout << "before: A is\n" << A << "\n";
//
//  calling the beast
//
    beast(A);
    std::cout << "after: A is\n" << A << "\n";

    return 0;
}

Compile and Run

$shell> cd flens/examples                                                         
$shell> clang++ -I/opt/local/include/ -I$HOME/MTL/usr/include -o design-flaws-mtl4 design-flaws-mtl4.cc                                                  
$shell> ./design-flaws-mtl4                                                       
before: A is
[0 1 2 3 4]
[1 2 3 4 5]
[2 3 4 5 6]
[3 4 5 6 7]
[4 5 6 7 8]
after: A is
[  0   1   2   3   4]
[  1 666   3   4   5]
[  2   3   4   5   6]
[  3   4   5   6   7]
[  4   5   6   7   8]