【问题标题】:Compilation Error Using template programming with Eigen C++ library使用带有 Eigen C++ 库的模板编程时出现编译错误
【发布时间】:2013-11-11 04:34:51
【问题描述】:

我下载了 Eigen (3) 库并开始使用它。我写了一个模板函数,并在函数内部声明了一个“模板类型”的局部变量。我收到以下编译错误。


$ 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”如下所示。


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

我也试过使用'typename Type1 tmp = matrix(0, 0);'
这也没用!

如何解决这个问题? 在普通的 C++ 模板编程中(没有 Eigen),我可以在模板函数中定义一个局部变量为 'Type1 tmp;"

【问题讨论】:

  • 什么是Type1?您在问题中显示的程序不是产生错误的程序。请出示真正的程序。
  • 很抱歉在他最初的帖子中遗漏了部分代码。 Type1 实际上是“模板类型名”
  • 不过,简而言之,看起来来自调用 matrix(0, 0) 的返回(我不太明白,但还早)与 Type1 的类型不匹配 - 不管是什么,你还没有向我们展示 Type1 的定义,大概在某个 typedef 的某个地方。
  • 我建议你了解SSCCE 是什么。
  • 伙计们,代码丢失了&lt;&gt;,我现在收到了OP描述的错误。

标签: c++ templates compiler-errors eigen eigen3


【解决方案1】:

Eigen::MatrixBase&lt;Type1&gt; 中,Type1 不是标量类型,而是实际表达式的类型。在您的示例中,它将是 MatrixXd,但如果调用了 myFunc,例如 m.block(...),那么 Type1 将是一个 Block<...>。要获取标量类型,可以使用 Type1::Scalar:

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

如果您需要类似于Type1 的矩阵类型,请使用Type1::PlainObject,例如:

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

【讨论】:

  • 感谢您的回复。正如你所建议的,我使用了 Type1::Scalar,它现在可以工作了。
  • 我认为底部代码应该是Type1::PlainObject,而不是PlainObjectType
  • @ofloveandhate,你说得对,我已经更新了答案。
【解决方案2】:

看起来MatrixBase 使用“CRTP”(参见here),模板参数实际上是从它派生的类型。因此,在您使用myFunc() 方法时,Type1 实际上代表Eigen::MatrixXd,并且我认为 认为Type1 是双重的。所以,这一行:

Type1 tmp = matrix(0, 0);

在这个库的文档(见here)中,MatrixXd 的 typedef 是一个双精度矩阵,所以我猜matrix(0, 0) 的返回值是一个双精度值,而 tmp 是 Type1Eigen::MatrixXd,一个不会进入另一个。

扫描文档我认为您的函数将Matrix 作为参数可能会更好,这样标量类型应该可用。像这样的:

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

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

【讨论】:

  • 好的,错误输出比我想象的更容易误导。你不能使用this 来获取底层数据类型吗?
  • 并非完全误导。在错误消息中Eigen::DenseCoeffsBase&lt;Eigen::Matrix&lt;double, -1, -1&gt;, 1&gt;::Scalar 指的是double(在您的情况下),然后消息继续说它不能将其转换为Eigen::Matrix&lt;double, -1, -1&gt;,即Type1,该类型派生自MatrixBase 和也是它的模板参数。简单! (不是!)至于其他解决方案,很可能是 - 我不知道这个库,我只是快速扫描了文档以查找错误来源。
  • 这可能是 MSVC 可以给出最有用错误的情况之一(因为它通常会列出与模板实例化相关的所有类型)。无论如何,找到真正的问题:-).
  • 很高兴我能帮上忙。格拉德仍然赞成投票和打勾。 ;-)
【解决方案3】:

在您的代码中,Type1 被推断为double(因为Eigen::MatrixXd is defined that way)。

然后你正在尝试做

Type1 tmp = matrix(0, 0);

而且我担心我的 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.

这告诉我你不能像那样调用matrix,用两个 0 作为参数。这也是一种奇怪的语法,因为 MatrixBase 类没有您似乎试图调用的 operator()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-05
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    相关资源
    最近更新 更多