This forum has been archived. All content is frozen. Please use KDE Discuss instead.

Overload for VectorXd with specific size

Tags: None
(comma "," separated)
Horus
Registered Member
Posts
296
Karma
0
OS
Hello,

I have a function that is only valid vor Vector2d, but it is also called with VectorXd of size 2:

Code: Select all
#include <Eigen/Dense>

void f2d(Eigen::Vector2d & arg) {
  return;
}

template<typename Derived>
void fXd(Eigen::MatrixBase<Derived>& arg) {
  return;
}

int main(int argc, char *argv[])
{
  Eigen::Vector3d a(1,2,3);
  Eigen::Vector2d b(1,2);
  Eigen::VectorXd c = Eigen::VectorXd::Zero(2);

  // f2d(a); // does not work, of course
  f2d(b); // works, of course
  // f2d(c); // does not work, either

  fXd(a); // works with template
  fXd(b); // works with template
  fXd(c); // works with template

  return 0;
}



Calling f2d with b works and with a fails, of course.

Calling fXd works with any vector, but also with Vector3d.

Is there a way to formulate a function signature that only accepts VectorXd of size 2 and Vector2d?

Or is impossible, because the size of a VectorXd is a runtime property and I should just use runtime assertions to make
sure it's only called with a vector of size 2?

Thanks!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
You can use Ref<>:
Code: Select all
void f2d(Ref<Vector2d> arg) {
  // here you can use arg as a read-write Vector2d, e.g.:
  arg = 2*arg;
  return;
}
Horus
Registered Member
Posts
296
Karma
0
OS
Thanks, that works like that:

Code: Select all
#include <Eigen/Dense>

using namespace Eigen;

void f2d(const Ref<Vector2d> & arg) {
  return;
}

int main(int argc, char *argv[])
{
  Vector3d a(1,2,3);
  Vector2d b(1,2);
  VectorXd c = VectorXd::Zero(2);

  f2d(b); // works, of course
  f2d(c); // does not work, either

  return 0;
}


Is it possible to add an overload that is called by VectorXd of size 3? Just adding a function that takes an const Ref<Vector3d> & seems to be ambigous to the compiler.

We are converting our application from a self-written LA lib to Eigen and my actual problem looks like that:

Code: Select all
template<typename Derived>
double GeometryComputations:: triangleArea
(
  const Eigen::MatrixBase<Derived>& a,
  const Eigen::MatrixBase<Derived>& b,
  const Eigen::MatrixBase<Derived>& c )
{
  if ( a.size() == 2 ){
    Eigen::VectorXd A = b;
    A -= a;
    Eigen::VectorXd B = c;
    B -= a;
    return 0.5 * (A(0)*B(1) - A(1)*B(0));
  }
  else {
    assertion ( a.size() == 3, a.size() );
    Eigen::VectorXd A = b; A -= a;
    Eigen::VectorXd B = c; B -= a;
    return 0.5 * A.cross(B).norm();
  }
}


This worked on our previous lib, because there were no compile time sized vectors. My idea is to split this function into two functions. One that takes an Vector2d and VectorXd of size=2, one that takes an Vector3d and VectorXd of size=3.

Ok, my bad... it seems to be working with the easy solution of just converting to Vector3d resp. Vector2d and taking VectorXd as arguments.

Still, out of interest, do you see a way to formulate the overloads, how I said above? Also the performance impact on the runtime conversion bothers me.

Thx!
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
You need 3 overloads, one taking a Ref<Vector2d>, one taking a Ref<Vector3d>, and one for VectorXd doing the branching at runtime:

if(a.size()==2) foo(a.head<2>();
else if(a.size()==3) foo(a.head<3>();

with perhaps the help of std::enable_if to disambiguate.


Bookmarks



Who is online

Registered users: Bing [Bot], Google [Bot], Sogou [Bot]