[英]Copy templated function argument in Eigen
I am writing a generic class that utilizes Eigen data types. 我正在编写一个利用Eigen数据类型的泛型类。 I already have problems assigning constructor arguments to class member variables. 我已经有问题将构造函数参数分配给类成员变量。 A simplified version of my code would be: 我的代码的简化版本是:
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.
}
};
My question is now what data type M
should be? 我现在的问题是M
应该是什么数据类型? I tried a variety of options, such as: 我尝试了各种选项,例如:
Eigen::internal::plain_matrix_type_column_major<Derived> M;
Eigen::DenseBase<Derived> M;
but they just generate different errors. 但他们只会产生不同的错误。 Note that I use C++17 and expect the class template parameter to be inferred from the constructor. 请注意,我使用C ++ 17并期望从构造函数中推断出类模板参数。
The declaration of the Eigen::Matrix
variable M
should be something like: Eigen::Matrix
变量M
的声明应该类似于:
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. 不要担心这里没有nullptr dereference,因为decltype中的代码没有被执行。
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;
也不要忘记#include <type_traits>
并使用std::
前缀所有内容或using namespace std;
添加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 ): 用法示例( 关于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>>();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.