Re: [eigen] Ref<> Problem

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]




On Fri, Dec 5, 2014 at 1:21 AM, gabriel nützi <gnuetzi@xxxxxxxxx> wrote:
I have read bug 884 through, and did not understand every bit I must say :-)

But for one thing I am sure:
For me it sounds absolutely strange if Ref<>  is an object which holds in itself some kind of temporary object (m_object)
But considering C++ reference which can hold temporary data it is absolutely legit.

So did I understand correctly

Ref<MatrixXd> a;              is a reference to a MatrixXd and “a” should not in any circumstances bind to some kind of temporary Eigen object (_expression_/block, what ever?) (like double & a;)
Ref< const MatrixXd> a;   is a reference to a MatrixXd which is CONSt and might bind to a temporary Eigen object (_expression_/block, what ever?) (like const double &)

Is that the behaviour which Ref<> already produces or are there some more subtleties?

Yes that's  basically it. However what can be referenced without a temporary is more subtle: storage order should match, strides should match, alignement should match, etc.:

typedef Ref<const MatrixXd> R;
MatrixXd a;
RowMatrixXd b;
Matrix4d c;

R r(a); // no temp
R r(a.block(...)); // no temp
R r(c); // no temp
R r(b); // temp
R r(b.transpose()); // no temp
R r(a+a); // temp
R r(2*a); // temp
R r(a.transpose()); // temp


what happens with   
Ref< const MatrixXd &> a; ????
Ref< MatrixXd &> a; ????
 
does not compile.

gael
 

Thanks a lot!



Am 04.12.2014 um 21:09 schrieb Gael Guennebaud <gael.guennebaud@xxxxxxxxx>:



On Thu, Dec 4, 2014 at 12:05 PM, Christoph Hertzberg <chtz@xxxxxxxxxxxxxxxxxxxxxxxx> wrote:
On 04.12.2014 10:41, Gabriel wrote:
struct A{
         // constructor does not generate a temporary:
         template<class Derived>
         A(const Eigen::MatrixBase<Derived> & in) : r(in) {}
         // initializing r might create a temporary but that is stored in r


         A  & operator=(const A & other)
         {
             new (&r) Eigen::Ref<const Eigen::MatrixXd>(other.r);

             return *this;
         }

         Eigen::Ref<const Eigen::MatrixXd> r;
     };

Is that correct, it seems to work :-)?

That works for some parts, but there are still some pitfalls:

int main() {
  Eigen::MatrixXd M = Eigen::MatrixXd::Identity(3,3);

  A A1(3*M);   // creates temporary in A1
  {
    A A2(2*M); // creates temporary in A2
    A1 = A2;   // temporary in A1 is not destructed! --> LEAK
  } // temporary in A2 gets destructed, invalid reference in A1!

  std::cout << A1.r << std::endl; // PROBLEM!
}

So generally, like C++ references, Ref should be considered as initialize-once variables. And, like in C++, strange things can happen, if the variable by which it got initialized runs out of scope before the reference does.

These pitfalls go away if the creation of a temporary is disabled in the Ref<> object (bug 884) which seems to be OK in Gabriel's use case.

gael 




Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/