I have encountered a problem in a function overload for different kinds of Eigen matrices (a column and a matrix to be precise). The overload fails when the input is the result of some simple arithmetic. In particular:
#include <Eigen/Eigen>
#include <iostream>
typedef Eigen::Matrix<double, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> MatD;
typedef Eigen::Matrix<double, Eigen::Dynamic, 1, Eigen::ColMajor> ColD;
ColD multiply(const ColD &A){ return 2. * A; }
MatD multiply(const MatD &A){ return 2. * A; }
int main()
{
ColD A = ColD::Ones(10);
MatD B = MatD::Ones(10,10);
// overload is correct
std::cout << multiply(A) << std::endl;
std::cout << multiply(B) << std::endl;
// compiler error: "error: call to 'multiply' is ambiguous"
std::cout << multiply(A+A) << std::endl;
std::cout << multiply(B+B) << std::endl;
return 0;
}
I.e. the overload based on A
and B
is compiled correctly. But the compiler is unable to identify the correct overload when I do A+A
and B+B
. I could solve this by doing two lines, potentially using some temporary variable, but this I don't want to do. How can I get this overload to work for this 'one-liner'?
I presume it is a particularity of Eigen, but am so far unable to understand exactly which particularity and how I can avoid it.
As explained in the comment, Eigen's operators do not produce plain matrices or vectors but operation objects (e.g. Eigen::CwiseBinaryOp<...>
).
You can either convert the operation to a plain matrix like so...
std::cout << multiply(ColD(A + A)) << std::endl;
std::cout << multiply(MatD(B + B)) << std::endl;
... or make multiply
a template that accepts all kinds of formats. The syntax becomes a bit ugly, however:
template <typename Derived>
Eigen::Matrix<
typename Eigen::internal::traits<Derived>::Scalar,
Eigen::internal::traits<Derived>::RowsAtCompileTime,
Eigen::internal::traits<Derived>::ColsAtCompileTime>
multiply(const Derived& A)
{
return 2.0 * A;
}
The template parameter is Derived
, which can be a matrix, a vector, or any of Eigen's operation objects. The return value is a Eigen::Matrix
whose characteristics we extract from Derived
via the traits
template.