3

Is it possible to define a pointer to a Eigen::Map object? The original code is quite complex but here is what I am trying to achieve (pseudo code)

void testfunction1(... XPtr){
  // XPtr is a pointer
  // create a vector, map it to a Map object and make XPtr point to the latter

  VectorXd Xnew(9);
  Xnew <<  10, 20, 30, 40, 50, 60, 70, 80, 90;
  Map<VectorXd> XnewMap(Xnew.data(), 9); 

  // make XPtr point to XnewMap so that Xnew data can be 
  // accessed outside testfunction1()
  // ... how? I suspect this to involve some dynamic memory allocation
};

void testfunction2(bool yes){
  // main function

  VectorXd XR(9);
  XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
  const Map<VectorXd> X(XR.data(), 9); // yes the mapped version is needed

  // create a pointer to X, say XPtr
  // ... how?

  if(yes){ // make XPtr point to XnewMap which is defined in testfunction1()
     testfunction1(XPtr);
   };

  //... some computations

  // make XPtr point again to X
  // ... how?

};
halfer
  • 19,824
  • 17
  • 99
  • 186
itQ
  • 59
  • 3
  • 10

1 Answers1

1

First of all no need to use pointers here because Map is already essentially a pointer, so it would be simpler so update the Map object with placement new. Nonetheless, your current design would require allocation within testfunction1 and deallocation within testfunction2 in case it has been allocated, which is not really safe. So better adopt a functional design by putting "some computations" within a function (or a named lambda), make testfunction1 return by value:

VectorXd testFunction1() { return Xnew; }

void testfunction2(bool yes){
  VectorXd XR(9);
  XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
  const Map<VectorXd> X(XR.data(), 9);

  auto func = [&] (Eigen::Ref<VectorXd> X) {
    /* some computation */
  }

  if(yes) func(testfunction1());
  else    func(X);
};

If you really want to keep your current logic, then here is a self-contained example using placement new:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;

void testfunction1(Map<VectorXd> &XMap){
  double * Xnew = new double[9];
  ::new (&XMap) Map<VectorXd>(Xnew,9);
  XMap << 10, 20, 30, 40, 50, 60, 70, 80, 90;
};

int main()
{
  bool yes = true;

  VectorXd XR(9);
  XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
  Map<VectorXd> X(XR.data(), 9);

  if(yes) testfunction1(X);

  // use X ...
  cout << X.transpose() << endl;

  // restore X and free memory allocated in testfunction1
  if(yes){
    delete[] X.data();
    ::new (&X) Map<VectorXd>(XR.data(),9);
  }

  cout << X.transpose() << endl;
}

which is pretty bad because it can leak if an exception is raised when using X. You could workaround manual memory management by asking testFunction1 to return a VectorXd (or anything that handle memory allocation/deallocation on its own) and do the placement new in the main function:

#include <iostream>
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;

VectorXd testfunction1(){
  VectorXd Xnew(9);
  Xnew << 10, 20, 30, 40, 50, 60, 70, 80, 90;
  return Xnew;
};

int main()
{
  bool yes = true;

  VectorXd XR(9);
  XR <<  1, 2, 3, 4, 5, 6, 7, 8, 9;
  Map<VectorXd> X(XR.data(), 9);

  {
    VectorXd X2;
    if(yes) {
      X2 = testfunction1(); // shallow copy thanks to move semantic
      ::new (&X) Map<VectorXd>(X2.data(),9);
    }

    // use X ...
    cout << X.transpose() << endl;

    // restore X
    ::new (&X) Map<VectorXd>(XR.data(),9);
  }

  cout << X.transpose() << endl;
}

Finally, if the content of X should be read-only, then use Map<const VectorXd> and not const Map<VectorXd> as in your initial question.

ggael
  • 28,425
  • 2
  • 65
  • 71
  • Thanks for your answer. This is what my current code is doing but it makes it difficult to read as the if else statement requires different func, but I'll accept your answer as it may be useful to others. However, I am still wondering how to declare a pointer to Map<...> – itQ Sep 06 '17 at 10:57
  • Nothing tricky, just declare `typedef const MapVectorXd ConstMapVectorXd;` and then use `ConstMapVectorXd*`, but you have to deal with complex dynamic memory allocation for both the data referenced by the new Map and the Map object itself, which is always prone to errors and memory leak. If you modify the Map object itself using [placement new](https://eigen.tuxfamily.org/dox/group__TutorialMapClass.html#title3), you will "only" have to deal with the allocation/deallocation of the referenced data, better, not not satisfactory. – ggael Sep 06 '17 at 12:09