Reputation: 121
template <typename Derived>
void Fun(const std::vector<Eigen::MatrixBase<Derived>> &seqs);
void Test() {
std::vector<Eigen::MatrixXd> _seqs;
Fun(_seqs);
}
As tutored by functions taking eigen types, Eigen::MatrixBase<Derived>
should accept Eigen::MatrixXd
. However, the above code could not compiled with error message says mismatched types ‘Eigen::MatrixBase<Derived>’ and ‘Eigen::Matrix<double, -1, -1>’
and the template arguments deduction failed.
So why this happens and how should we deal with it?
Thanks
Upvotes: 3
Views: 846
Reputation: 18807
I don't see a point in accepting a vector
of Eigen::MatrixBase
objects.
I don't know your use case, but it usually only makes sense to store the actual Matrix
objects inside the vector
. And passing that to a templated function is easy:
template<class S, int rows, int cols>
void func(std::vector<Eigen::Matrix<S, rows, cols> > const &) { }
Note: You can add more template parameters, for template parameters which have defaults, e.g., MatrixOptions or the allocator of the vector
. The same way, you can leave out template parameters, e.g., if S
is always double
.
Upvotes: 1
Reputation: 38415
You should declare function and variable like below
template <typename Derived>
void Fun(const std::vector<std::unique_ptr<Eigen::MatrixBase<Derived>>> &seqs);
std::vector<std::unique_ptr<Eigen::MatrixBase<Derived>>> _seqs;
And fill the vector with pointers to Eigen::MatrixXd
:
_seq.emplace_back(new Eigen::MatrixXd);
UPDATE @chtz informed me that Eigen::MatrixBase
(inherits struct EigenBase
) has no virtual destructor. Thus my solution above is not proper. The only ways left
std::transform()
to get std::vector<Eigen::MatrixBase<Derived>*>
from std::vector<std::unique_ptr<Eigen::MatrixBase<Derived>>>
.Upvotes: 1
Reputation: 13040
This is because the rule that template-name<T>
as a whole parameter (ignoring reference and cv-qualifiers) can be deduced from D
if D
is derived from template-name<T>
for some T
. This rule does not apply for std::vector<template-name<T>>
.
Even if you explicitly specify the type, since there is no valid conversion from std::vector<Derived>
to std::vector<Base>
, the call is still ill-formed.
Besides S.M.'s solution, you can use meta programming.
template <
typename T,
// enable only if T is derived from Eigen::MatrixBase<T>
typename std::enable_if_t<std::is_base_of<Eigen::MatrixBase<T>, T>::value, int> = 0
>
void Fun(const std::vector<T>&);
Upvotes: 3