I am trying to write a function that accepts only lvalue Eigen expressions passed via const
references. My first idea was to keep only the overload const Eigen::MatrixBase<Derived>&
and delete
the Eigen::MatrixBase<Derived>&&
one. To my surprise, the delete
d function was not part of the overload candidate set. So I tried the code below
#include <iostream>
#include <Eigen/Dense>
#define PRINT_MY_NAME std::cout << __PRETTY_FUNCTION__ << '\n'
template<typename Derived>
void f(const Eigen::MatrixBase<Derived>&) // (1)
{
PRINT_MY_NAME;
}
template<typename Derived>
void f(Eigen::MatrixBase<Derived>&&) // (2)
{
PRINT_MY_NAME;
}
int main()
{
Eigen::MatrixXd A;
f(A); // invokes (1)
f(A + A); // invokes also (1) !!!
}
which outputs (gcc5.2)
void f(const Eigen::MatrixBase&) [with Derived = Eigen::Matrix < double, -1, -1>]
void f(const Eigen::MatrixBase&) [with Derived = Eigen::CwiseBinaryOp < Eigen::internal::scalar_sum_op < double>, const Eigen::Matrix < double, -1, -1>, const Eigen::Matrix < double, -1, -1> >]
so clearly the rvalue overload is not considered. It is now clear for me that the second one is not a better match, since I pass a rvalue Eigen expression, which is convertible to Eigen::MatrixBase<>
, but is not the exact same type. Now comes my question:
- How can I disable or detect rvalue Eigen expressions passed as parameters for
f
? The issue is that an expression can have an arbitrary type (Eigen uses expression templates), likeCwiseBinaryOp<...CwiseBinaryOp<...>>
and so on. This is part of a larger problem in which I have a utility make-like function which takes a lvalue and binds it to aconst
reference expression in a class. If the expression is a rvalue, then all bets are off, since reference binding is not propagating via a constructor argument, so I want to forbid passing rvalue Eigen expressions.