7

我正在编写一个使用 Eigen 数据类型的通用类。我已经在将构造函数参数分配给类成员变量时遇到了问题。我的代码的简化版本是:

template <typename Derived>
class A
{
public:
  Eigen::Matrix<Derived> M; // error C2976: too few template parameters

A(const Eigen::DenseBase<Derived> & V)
{
  M = V.eval(); // I would want to snapshot the value of V.
}
};

我的问题现在M应该是什么数据类型?我尝试了多种选择,例如:

Eigen::internal::plain_matrix_type_column_major<Derived> M;
Eigen::DenseBase<Derived> M;

但它们只会产生不同的错误。请注意,我使用 C++17 并期望从构造函数中推断出类模板参数。

4

3 回答 3

5

Eigen::Matrix变量的声明M应该是这样的:

Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M; 

然后你的代码将编译。请参阅演示

可以在此链接中找到每个模板参数的详细说明。

于 2019-04-01T13:06:33.960 回答
3

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;
于 2019-04-01T13:13:38.493 回答
2

您的容器需要实际的“普通类型”作为模板参数:

template <typename PlainType>
class A
{
    PlainType M; 
public:
    template<class Derived>
    A(const Eigen::MatrixBase<Derived> & V) : M(V) {}
};

并且你需要一个额外的模板扣除规则:

template<class Derived>
A(const Eigen::MatrixBase<Derived> & V) -> A<typename Derived::PlainObject>;

用法示例(在 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>>();
}
于 2019-04-01T15:08:52.893 回答