Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Non-const reference of Eigen matrix only bind with dynamic types and not with non-dynamic types

I have an Eigen (3.4.0) related question that really troubles me. In this C++ code, there’s a function pass_by_nonconst_ref which takes a non-const reference to a eigen matrix, and that does some work on the matrix.

#include <iostream>
#include "Eigen/Eigen"

using namespace std;

// A function that takes a non const reference to a vector
void pass_by_nonconst_ref(Eigen::Matrix<float, -1, 1>& vec) {
        // do some work on your matrix...
        vec(0) = 1;
}

int main() {
        // This works without any problem.
        Eigen::Matrix<float, -1, 1> x1(3);
        x1 << 0.0, 0.0, 0.0 ;
        pass_by_nonconst_ref(x1);
        cout << "x = " << x1 << endl ;
        
        // But this does not !!!!
        Eigen::Matrix<float, 3, 1> x2;
        x2 << 0.0, 0.0, 0.0 ;
        // if you uncomment this line, it won't compile...
        // pass_by_nonconst_ref(x2);
        cout << "x = " << x2 << endl ;

        // And to check that x2 is not a temporary?
        Eigen::Matrix<float, 3, 1> x3;
        x3 << 0.0, 0.0, 0.0 ;
        x3(0) = 1;
        cout << "x = " << x3 << endl ;// this works

        return 0;
}

This code only compiles if I pass to the function an object the type Eigen::Matrix<float, -1, 1>. If I use instead Eigen::Matrix<float, 3, 1>, then there is the following compilation error:

error: cannot bind non-const lvalue reference of type ‘Eigen::Matrix<float, -1, 1>&’ to an rvalue of type ‘Eigen::Matrix<float, -1, 1>’
   22 |  pass_by_nonconst_ref(x2);

The only difference (that I see) is that x2 knows it only has 3 rows, whereas x1 has a dynamic number of rows. I am aware that a non-const reference can’t bind to a temporary, but I really don’t see why x2 can be considered as one and not x1.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I can’t understand why I have to specify the dynamic type to make it work. It got me quite curious. Is there something obvious that I am missing ? I suspect it is related to type conversion.

>Solution :

Eigen::Matrix<float, 3, 1> is a different type than Eigen::Matrix<float, -1, 1>. The only reason the function call resolves at all when you call it with x2 is that Eigen supplies an implicit cast operator that knows how to create a dynamic matrix from a fixed-size one. However, what this means is that a temporary is created and passed, which is what is causing your error. See the Eigen documentation at the section "In which cases do functions taking a plain Matrix or Array argument fail?"

That same page provides alternate ways to write your function so that it takes Eigen matrices of all types. If you use this signature, your program compiles and runs:

template <typename Derived>
void pass_by_nonconst_ref(Eigen::MatrixBase<Derived>& vec) {
        // do some work on your matrix...
        vec(0) = 1;
}

Still, beware of temporaries, since Eigen passes around expression types. The documentation page suggests (argh!) in some cases accepting a const reference and casting away the constness. If you pass a plain local Eigen matrix object as I wrote above, you should be fine.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading