Eigen + C++11's auto gotcha

Alec Jacobson

September 10, 2014

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;