简体   繁体   English

编译错误使用Eigen C ++库进行模板编程

[英]Compilation Error Using template programming with Eigen C++ library

I downloaded Eigen (3) library and started using it. 我下载了Eigen(3)库并开始使用它。 I wrote a template function and declared a local variable of 'template type' inside the function. 我写了一个模板函数,并在函数内声明了一个'模板类型'的局部变量。 I am getting the following compilation error. 我收到以下编译错误。


$ g++ EigenTest.cpp

EigenTest.cpp: In instantiation of ‘void myFunc(Eigen::MatrixBase<Derived>&) [with Type1 = Eigen::Matrix<double, -1, -1>]’:
EigenTest.cpp:24:10:   required from here
EigenTest.cpp:16:26: error: conversion from ‘Eigen::DenseCoeffsBase<Eigen::Matrix<double, -1, -1>, 1>::Scalar {aka double}’ to non-scalar type ‘Eigen::Matrix<double, -1, -1>’ requested
   Type1 tmp = matrix(0, 0);

"EigenTest.cpp" is given below. “EigenTest.cpp”如下。


#include "Eigen/Dense"

#include <iostream>

template<typename Type1>
void myFunc(Eigen::MatrixBase<Type1>& matrix)
{
int i=matrix.rows();
Type1 tmp = matrix(0, 0);           // getting compiler error here
std::cout<<"tmp is ->"<<tmp<<std::endl;
}

int main()
{
Eigen::MatrixXd m(2,2);
m.setConstant(100); 
myFunc(m);
return 0;
}

I also tried using 'typename Type1 tmp = matrix(0, 0);' 我也尝试使用'typename Type1 tmp = matrix(0,0);'
This also didn't work! 这也行不通!

How to fix this? 如何解决这个问题? In normal C++ template programming (without Eigen), I can define a local variable inside a template function as 'Type1 tmp;" 在普通的C ++模板编程中(没有Eigen),我可以在模板函数中将局部变量定义为'Type1 tmp;'

In Eigen::MatrixBase<Type1> , Type1 is not a scalar type but the type of the actual expression. Eigen::MatrixBase<Type1>Type1不是标量类型,而是实际表达式的类型。 In your example it will be MatrixXd but if myFunc is called on, eg, m.block(...), then Type1 will be a Block<...>. 在您的示例中,它将是MatrixXd,但如果调用myFunc,例如m.block(...),则Type1将是Block <...>。 To obtain the scalar type, you can use Type1::Scalar: 要获取标量类型,可以使用Type1 :: Scalar:

template<typename Type1>
void myFunc(Eigen::MatrixBase<Type1>& matrix)
{
  typename Type1::Scalar Scalar;
  Scalar tmp = matrix(0, 0);
}

And if you need a matrix type that is similar to Type1 , use Type1::PlainObject , eg: 如果您需要一个类似于Type1的矩阵类型,请使用Type1::PlainObject ,例如:

typename Type1::PlainObject mat = 2 * matrix * matrix.transpose();

It looks like MatrixBase uses the "CRTP" (see here ), the template argument is actually the type deriving from it. 看起来MatrixBase使用“CRTP”(参见此处 ),模板参数实际上是从中派生的类型。 Thus in your use of the method myFunc() , Type1 is actually representing Eigen::MatrixXd , and I think that you think Type1 is a double. 因此,在你使用方法myFunc()Type1实际上代表了Eigen::MatrixXd ,我认为 认为Type1是一个double。 So, this line: 所以,这一行:

Type1 tmp = matrix(0, 0);

In the documnetation for this library (see here ) the typedef for MatrixXd is a matrix of doubles, so I guess the return from matrix(0, 0) is a double, and as tmp is of Type1 which is Eigen::MatrixXd , the one will not go into the other. 在这个库的documnetation中(见这里 ), MatrixXd的typedef是一个双精度矩阵,所以我猜matrix(0, 0)的返回是一个double,而tmp是Type1Eigen::MatrixXd ,一个人不会进入另一个人。

Scanning the docummentation I think it MIGHT be better for your function to take a Matrix as an argument, that way the scalar type should be available. 扫描docummentation我认为你的函数可能更好地将Matrix作为参数,这样标量类型应该是可用的。 Something like this: 像这样的东西:

template<class T, int rows, int cols, int opts, int maxR, int maxC > 
void myFunc( Eigen::Matrix<T, rows, cols, opts, maxR, maxC>& matrix )
{
    T tmp = matrix(0, 0);
}

(Looks dreadful though!!! ;-) ) (虽然看起来很可怕!!! ;-))

In your code, Type1 is deduced to be double (because Eigen::MatrixXd is defined that way ). 在你的代码中, Type1被推断为double (因为Eigen::MatrixXd是这样定义的 )。

You are then trying to do 你正在尝试做

Type1 tmp = matrix(0, 0);

And I'm afraid my Eigen knowledge isn't enough, so I ran it through Clang 3.3, and got this error: 而且我担心我的Eigen知识还不够,所以我通过Clang 3.3运行它,并得到了这个错误:

test.cpp:9:7: error: no viable conversion from 'Scalar' (aka 'double') to
      'Eigen::Matrix<double, -1, -1, 0, -1, -1>'
Type1 tmp = matrix(0, 0);           // getting compiler error here
      ^     ~~~~~~~~~~~~
test.cpp:17:1: note: in instantiation of function template specialization
      'myFunc<Eigen::Matrix<double, -1, -1, 0, -1, -1> >' requested here
myFunc(m);
^
/usr/include/eigen3/Eigen/src/Core/Matrix.h:210:5: note: candidate constructor not viable:
      no known conversion from 'Scalar' (aka 'double') to
      'internal::constructor_without_unaligned_array_assert' for 1st argument
    Matrix(internal::constructor_without_unaligned_array_assert)
    ^
/usr/include/eigen3/Eigen/src/Core/Matrix.h:284:25: note: candidate constructor not
      viable: no known conversion from 'Scalar' (aka 'double') to 'const
      Eigen::Matrix<double, -1, -1, 0, -1, -1> &' for 1st argument
    EIGEN_STRONG_INLINE Matrix(const Matrix& other)
                        ^
/usr/include/eigen3/Eigen/src/Core/Matrix.h:272:25: note: candidate template ignored:
      could not match 'MatrixBase<type-parameter-0-0>' against 'double'
    EIGEN_STRONG_INLINE Matrix(const MatrixBase<OtherDerived>& other)
                        ^
/usr/include/eigen3/Eigen/src/Core/Matrix.h:292:25: note: candidate template ignored:
      could not match 'ReturnByValue<type-parameter-0-0>' against 'double'
    EIGEN_STRONG_INLINE Matrix(const ReturnByValue<OtherDerived>& other)
                        ^
/usr/include/eigen3/Eigen/src/Core/Matrix.h:303:25: note: candidate template ignored:
      could not match 'EigenBase<type-parameter-0-0>' against 'double'
    EIGEN_STRONG_INLINE Matrix(const EigenBase<OtherDerived> &other)
                        ^
1 error generated.

which is telling me you cannot call matrix like that, with two 0's as arguments. 这告诉我你不能像这样调用matrix ,用两个0作为参数。 It's also weird syntax because the MatrixBase class does not have an operator() which you seem to be trying to calling. 这也是一种奇怪的语法,因为MatrixBase类没有你似乎试图调用的operator()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM