0

I'm having trouble reassigning a Block. In the code below I store the matrix A in two different ways:

  1. as 3 ArrayXds, one for each row
  2. as an ArrayXXd

.

// data

ArrayXXd A (3, 3);
A << 0, 1, 2, 3, 4, 5, 6, 7, 8;

std::vector<ArrayXd> A_rows = {A.row(0), A.row(1), A.row(2)};

// std::vector<ArrayXd> solution

// first row
ArrayXd & current_row = A_rows[0];
// read it, write it, do stuff
// start working with the second row
current_row = std::ref(A_rows[1]);
cout << current_row << endl << endl; // prints 3 4 5
cout << A << endl; // A is unchanged

// Eigen solution

// first row
Block<ArrayXXd, 1, -1> && current_row_block = A.row(0);
// read it, write it, do stuff
// start working with the second row
current_row_block = std::ref(A.row(1)); // doesn't compile
cout << current_row_block << endl;
cout << A << endl;

The error message is:

error: use of deleted function 'void std::ref(const _Tp&&) [with _Tp = Eigen::Block<Eigen::Array<double, -1, -1>, 1, -1, false>]'
 current_row_block = std::ref(A.row(1));
                                      ^

Is it possible to fix the second approach or should I move to storing the matrix as std::vector<ArrayXd>?

Related question: Passing a reference of a vector element to a threaded function

Community
  • 1
  • 1
user357269
  • 1,835
  • 14
  • 40
  • Are you looking to avoid using an `Eigen::Map`? – Avi Ginsburg Aug 01 '16 at 19:12
  • @AviGinsburg, not particularly. I was thinking of using it to convert the `std::vector` into and `ArrayXXd` when I'm done. What did you have in mind? – user357269 Aug 01 '16 at 19:17
  • Why do you have a `std::vector` in the first place? – Avi Ginsburg Aug 01 '16 at 19:35
  • @AviGinsburg, my code eventually returns an `ArrayXXd` so I was trying to save on copying, but yeah, that seems like the way to go – user357269 Aug 01 '16 at 19:40
  • Huh? How does that save on copying? The memory pointed to in the `vector` isn't contiguous. It's a vector of objects, each of which has a data set somewhere in memory, not contiguous. – Avi Ginsburg Aug 01 '16 at 19:41
  • @AviGinsburg, ah thank you, that makes sense. I'm going to post a follow-up question on converting std::vector to ArrayXXd – user357269 Aug 01 '16 at 19:55
  • Read [this](http://stackoverflow.com/questions/33668485/eigen-and-stdvector/33669013#33669013) first. – Avi Ginsburg Aug 01 '16 at 20:01
  • Your `std::ref` approach seems to be broken. The statement `current_row = std::ref(A_rows[1]);` does not make `current_row` a reference to `A_rows[1]`. After that, `current_row` is still referencing `A_rows[0]`, whose content has been modified. – ggael Aug 02 '16 at 22:02
  • Thanks @ggael, you're right – user357269 Aug 03 '16 at 09:56

1 Answers1

0

You don't need a Block<...> to reference a row. You only need an index.

int current_row_id = 0;
std::out << A.row(current_row_id) << std::end;
current_row_id = 1;
std::out << A.row(current_row_id) << std::end;

For your std::vector<ArrayXd> approach, as you are make copies of the rows, you can not change the original A.

kangshiyin
  • 9,681
  • 1
  • 17
  • 29
  • This, instead of reassigning current_row_block to point to the second row, overwrites the first row – user357269 Aug 01 '16 at 19:16
  • @user357269 my bad. I forget operator= has been overloaded. – kangshiyin Aug 01 '16 at 19:24
  • I actually have several classes with similar behaviour, and part of the functionality is to have a `current_row` handle. In one of the classes this is an `ArrayXd &`, in another it would be `Block`. It's important that the internal workings of how `current_row` is produced be hidden, but it behave like an array. – user357269 Aug 01 '16 at 19:28
  • 1
    You may want to describe your original problem and why it should be hidden. I think none of the Eigen objects can be re-assigend, and you may have to re-design your classes. – kangshiyin Aug 01 '16 at 19:35
  • @kangshiyin You can re-assign a map with placement new. – Avi Ginsburg Aug 01 '16 at 19:40
  • @AviGinsburg then all objects can be re-assigned if placement new is an option. – kangshiyin Aug 01 '16 at 19:50
  • Are you recommending that I use placement new to reassign a `Block`? – user357269 Aug 01 '16 at 19:58
  • 1
    I'm recommending you to re-design your classes. Placement new probably works but will make the whole solution more ugly. – kangshiyin Aug 01 '16 at 20:00
  • @kangshiyin, I posted a more specific description of the problem I'm solving here: http://stackoverflow.com/questions/38707459/returning-all-rows-or-just-the-last-one – user357269 Aug 01 '16 at 20:24