I'm working on code with a lot of classes that template on a scalar type T and implement methods on containers like std::valarray<T>. I'd like to add support for Eigen containers, but I'm having trouble figuring out a way to template only on the scalar type while maintaining some of Eigen's flexibility.
For example, the Eigen docs suggest using Eigen::DenseBase<Derived>, but that seems to mean I'd have to change all my class defintions to template on the array type Derived and then use Derived::Scalar everywhere. Pretty intrusive just to support another container.
I could also just use Matrix<T,Dynamic,Dynamic>, but this is pretty restrictive. For the cases I care about, I was thinking a reasonable middle ground would be to use Ref<Matrix<T,Dynamic,Dynamic>> since that would cover Matrix and slices thereof with one interface. But this doesn't seem to work, and I'm not sure why. Here's a concrete example of what I mean:
#include<iostream>
#include<Eigen/Dense>
using namespace std;
using namespace Eigen;
double
sum1(const Ref<const Matrix<double,Dynamic,Dynamic>> &m)
{
double x = 0.0;
for (int j=0; j<m.cols(); ++j)
for (int i=0; i<m.rows(); ++i)
x += m(i,j);
return x;
}
template <typename T>
T
sum2(const Ref<const Matrix<T,Dynamic,Dynamic>> &m)
{
T x = 0.0;
for (int j=0; j<m.cols(); ++j)
for (int i=0; i<m.rows(); ++i)
x += m(i,j);
return x;
}
int main()
{
Matrix<double,Dynamic,Dynamic> a(2,2);
a << 0,2,1,3;
cout << "sum1(a) = " << sum1(a) << endl; // ok
cout << "sum2(a) = " << sum2(a) << endl; // error
cout << "sum2(a) = " << sum2<double>(a) << endl; // ok
return 0;
}
But I get errors when I compile:
$ clang++ -std=c++17 -I/usr/include/eigen3 eig2.cpp -o eig2
eig2.cpp:33:29: error: no matching function for call to 'sum2'
cout << "sum2(a) = " << sum2(a) << endl; // error
^~~~
eig2.cpp:19:1: note: candidate template ignored: could not match 'Ref' against
'Matrix'
sum2(const Ref<const Matrix<T,Dynamic,Dynamic>> &m)
^
1 error generated.
Is there a way to implement sum2 so that it supports Matrix and Ref and doesn't require explicit template arguments to use it?