1
votes

The following does not seem to work.

void Foo(Ref<VectorXd> v) {
  // modifies v
}

Eigen::VectorXd v;
Foo(v.cwiseAbs());

With the following error message

error: could not convert 'Eigen::ArrayBase::cwiseAbs() const with Derived = Eigen::ArrayWrapper, -1, 1, true>, -1, 1, false> >; Eigen::ArrayBase::CwiseAbsReturnType = Eigen::CwiseUnaryOp, const Eigen::ArrayWrapper, -1, 1, true>, -1, 1, false> > >; typename Eigen::internal::traits::Scalar = double' from 'const CwiseAbsReturnType {aka const Eigen::CwiseUnaryOp, const Eigen::ArrayWrapper, -1, 1, true>, -1, 1, false> > >}' to 'Eigen::Ref >'

Any suggestions why and how to fix?

1
What would you expect that to do?chtz

1 Answers

0
votes

This doesn't work, because two additional const qualifiers are required in order to mach the expression returned by .cwiseAbs(). This makes sense, because it should not be possible to modify the result of v.cwiseAbs() by a function that accepts this argument in the form of a reference. The following code compiles:

void Foo(const Ref<const VectorXd>& v) {
  std::cout << v << std::endl;
}

int main() {
  Eigen::VectorXd v(3);
  v << 1,-2,3;
  Foo(v.cwiseAbs());
}

With this modification, however, it is not allowed to modify v within Foo().

The simplest solution is probably to drop Ref<> and to use

 Foo(VectorXd v) {...}

instead. This generates a local copy, but this should not be an issue in terms of performance, moreover since it is anyhow impossible to avoid any copy if v is to be modified within Foo(). If Ref is kept in the signature of Foo, one can make a copy of v.cwiseAbs() and call Foo() with that copy:

void Foo(Ref<VectorXd> v) {...}
...
Eigen::VectorXd w = v.cwiseAbs();
Foo(w);

As suggested by @chtz, an alternative that is available with C++11 is

void Foo(VectorXd&& v) {...}

While this allows to modify v within Foo(), it can be somewhat dangerous to use because only a temporary is changed in Foo(). Modifications of v done in Foo() will not change v in main().