在 Eigen 中复制模板化函数参数
Copy templated function argument in Eigen
我正在编写一个使用 Eigen 数据类型的通用 class。我已经在将构造函数参数分配给 class 成员变量时遇到问题。我的代码的简化版本是:
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 并期望从构造函数中推断出 class 模板参数。
Eigen::Matrix
变量 M
的声明应该是这样的:
Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M;
然后你的代码将编译。参见 Demo。
可在 this link.
中找到每个模板参数的详细说明
声明类型的通用方法是使用生成它的声明作为源,这样您就不必查看特定的方法来声明复杂的模板类型,这是一个基于您的代码的示例:
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;
您的容器需要实际的 "plain type" 作为模板参数:
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>>();
}
我正在编写一个使用 Eigen 数据类型的通用 class。我已经在将构造函数参数分配给 class 成员变量时遇到问题。我的代码的简化版本是:
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 并期望从构造函数中推断出 class 模板参数。
Eigen::Matrix
变量 M
的声明应该是这样的:
Eigen::Matrix<typename Derived::Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> M;
然后你的代码将编译。参见 Demo。
可在 this link.
中找到每个模板参数的详细说明声明类型的通用方法是使用生成它的声明作为源,这样您就不必查看特定的方法来声明复杂的模板类型,这是一个基于您的代码的示例:
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;
您的容器需要实际的 "plain type" 作为模板参数:
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>>();
}