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

[SOLVED] Writing a template function that can take vectors and matrices

Tags: None
(comma "," separated)
djp
Registered Member
Posts
7
Karma
0
Hello,

I have the following problem: I have a function f, which maps a dynamic-sized vector to another vector. For convenience, I want to allow calling f with a matrix-parameter, in which case f should be applied rowwise.
As an example, consider a function f(x) that includes zeros in between the entries of x. My first try looked like this:

Code: Select all
#include
using namespace Eigen;

template
typename Derived::PlainMatrixType f(const Eigen::MatrixBase& x)
{
  if (x.IsVectorAtCompileTime) {
    typename Derived::PlainMatrixType result = Derived::PlainMatrixType::Zero(2*x.size());
    for (int i = 0; i  Matrix f(const Matrix& x);
template  Matrix f(const Matrix& x);
template  Matrix f(const Matrix& x);

but then the flexibility of calling f with any expression would be lost.

Best regards,
Martin
User avatar
bjacob
Registered Member
Posts
658
Karma
3
This is a classical issue of how to write templated c++ code.
The basic point is that the if() here:
Code: Select all
if (x.IsVectorAtCompileTime)

needs to be evaluated much earlier. The first thing to realize is that the object x is irrelevant here so you can as well write:
Code: Select all
if (Derived::IsVectorAtCompileTime)

I.e. only the type derived matters. So theoretically, the compiler should be able to evaluate that as soon as the type Derived is known. But unfortunately, in c++, the if() is only evaluated when your function body is getting compiler. What you want instead is a "meta if" that gets evaluated much earlier: as soon as the type "Derived" is known. This you can achieve by a different means: by template specialization.
Do something like:

Code: Select all
template
struct f_selector
{
  static typename Derived::PlainMatrixType run(const Eigen::MatrixBase& x)
  {
     // your function body in the vector case
  }
};

// now, make a partial template specialization
template
struct f_selector // false here means not Vector
{
  static typename Derived::PlainMatrixType run(const Eigen::MatrixBase& x)
  {
     // your function body in the non-vector case
  }
};

template
typename Derived::PlainMatrixType f(const Eigen::MatrixBase& x)
{
  return f_selector::run(x);
}


Join us on Eigen's IRC channel: #eigen on irc.freenode.net
Have a serious interest in Eigen? Then join the mailing list!


Bookmarks



Who is online

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