Copy templated function argument in Eigen
The declaration of the Eigen::Matrix
variable M
should be something like:
Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M;
Then your code will compile. See Demo.
The detailed description of each of the template parameters can be found at this link.
A generic way of declaring your type would be to use the declaration generating it as a source, this way you don't have to look at specific ways to declare complicated template types, this is an example based on your code:
decltype(static_cast<Eigen::DenseBase<Derived> *>(nullptr)->eval()) M;
don't worry there is no nullptr dereference here because the code inside decltype is not executed.
As pointed in the comments there's a cleaner way of writing this:
decltype(declval<Eigen::DenseBase<Derived>>().eval()) M;
and if you're worried that the type might be a reference and don't want that:
remove_reference_t<decltype(declval<Eigen::DenseBase<Derived>>().eval())> M;
also don't forget to #include <type_traits>
and either prefix everything with std::
or add using namespace std;
to your code.
To make the syntax simpler for future use add this to the beginning of your code:
template<typename T, typename T::f>
using member_function_return_t = remove_reference_t<decltype(declval<T>().f())>;
and than declare the variable as:
member_function_return_t<Eigen::DenseBase<Derived>, Eigen::DenseBase<Derived>::eval> M;
Your container needs the actual "plain type" as template argument:
template <typename PlainType>
class A
{
PlainType M;
public:
template<class Derived>
A(const Eigen::MatrixBase<Derived> & V) : M(V) {}
};
And you need an additional template deduction rule:
template<class Derived>
A(const Eigen::MatrixBase<Derived> & V) -> A<typename Derived::PlainObject>;
Usage example (on godbolt):
template<class X>
void bar(X&); // just to read full type of A
void foo(Eigen::Matrix2d const& M)
{
A a = M*M;
bar(a); // calls bar<A<Matrix2d>>();
}