在Eigen中复制模板化函数参数

时间:2019-04-01 12:56:05

标签: c++ c++17 eigen template-deduction class-template

我正在编写一个利用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并希望从构造函数中推断出类模板参数。

3 个答案:

答案 0 :(得分:4)

Eigen::Matrix变量M的声明应类似于:

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

然后您的代码将被编译。参见Demo

每个模板参数的详细说明可以在this link上找到。

答案 1 :(得分:3)

声明类型的一种通用方法是使用将其生成的声明作为源,这样,您不必查看声明复杂模板类型的特定方法,这是基于您的代码的示例:< / p>

decltype(static_cast<Eigen::DenseBase<Derived> *>(nullptr)->eval()) M;

请不要担心这里没有nullptr取消引用,因为不会执行decltype中的代码。

正如评论中指出的那样,有一种更简洁的编写方式:

decltype(declval<Eigen::DenseBase<Derived>>().eval()) M;

,如果您担心该类型可能是引用,而不希望这样做:

remove_reference_t<decltype(declval<Eigen::DenseBase<Derived>>().eval())> M;

也不要忘记为#include <type_traits>加上所有前缀std::或在代码中添加using namespace std;

要使语法更易于将来使用,请将其添加到代码的开头:

template<typename T, typename T::f>
using member_function_return_t = remove_reference_t<decltype(declval<T>().f())>;

然后将变量声明为:

member_function_return_t<Eigen::DenseBase<Derived>, Eigen::DenseBase<Derived>::eval> M;

答案 2 :(得分:1)

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

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>;

用法示例(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>>();
}