Eigen + C++11's auto gotcha

weblog/

Today marks the second time running into this gotcha involving Eigen and C++11's `auto`. It may even be a bug.

Here's the little example program:

``````Eigen::MatrixXd X(2,2);
X<<1,2,
3,4;
const auto mid = (X.colwise().maxCoeff()+X.colwise().minCoeff()).eval()*0.5;
cout<<mid<<endl;
X.setZero();
cout<<mid<<endl;
cout<<(X.colwise().maxCoeff()+X.colwise().minCoeff()).eval()*0.5<<endl;
``````

First I initialize a little matrix and then take the average of it's column-wise max and min vectors and store that in `mid`. I'm being careful to use `.eval()` because this should truly evaluate the expression. Then I print `mid`, zap `X` to zero, print `mid` again and---to double check---print the expression applied to the new all-zero `X`:

With clang this produces:

``````2 3
1 1.5
0 0
``````

With gcc I get:

``````2 3
-6.44115e-232  1.34339e+154
0 0
``````

So it seems that after X is set to zeros, `mid` contains some random bad value.

Changing `auto` above to `char` and reading the compiler error message I can reveal the true type of the expression

``````const ScalarMultipleReturnType {aka const Eigen::CwiseUnaryOp<Eigen::internal::scalar_multiple_op<double>, const Eigen::Matrix<double, 1, -1> >}
``````

Okay, so definitely not something simple like `Eigen::RowVector<...>` which I'd expected. Not sure why this is returning junk when the values of X change. For now, and for this simple example, the easy solution is to explicitly cast to the type I want:

``````const RowVector2d mid = (X.colwise().maxCoeff()+X.colwise().minCoeff()).eval()*0.5;
``````