【问题标题】:Eigen template on scalar type标量类型的特征模板
【发布时间】:2019-10-19 07:00:43
【问题描述】:

我正在编写包含大量类的代码,这些类以标量类型T 为模板,并在std::valarray<T> 等容器上实现方法。我想添加对 Eigen 容器的支持,但我无法找到一种方法来仅在标量类型上进行模板化,同时保持 Eigen 的一些灵活性。

例如,Eigen docs 建议使用Eigen::DenseBase<Derived>,但这似乎意味着我必须将我的所有类定义更改为数组类型Derived 上的模板,然后在任何地方使用Derived::Scalar。仅仅为了支持另一个容器就很麻烦。

我也可以只使用Matrix<T,Dynamic,Dynamic>,但这非常严格。对于我关心的情况,我认为一个合理的中间立场是使用Ref<Matrix<T,Dynamic,Dynamic>>,因为这将覆盖Matrix 及其一个接口的切片。但这似乎不起作用,我不确定为什么。这是我的意思的一个具体例子:

#include<iostream>
#include<Eigen/Dense>

using namespace std;
using namespace Eigen;

double
sum1(const Ref<const Matrix<double,Dynamic,Dynamic>> &m)
{
    double x = 0.0;
    for (int j=0; j<m.cols(); ++j)
        for (int i=0; i<m.rows(); ++i)
            x += m(i,j);
    return x;
}

template <typename T>
T
sum2(const Ref<const Matrix<T,Dynamic,Dynamic>> &m)
{
    T x = 0.0;
    for (int j=0; j<m.cols(); ++j)
        for (int i=0; i<m.rows(); ++i)
            x += m(i,j);
    return x;
}

int main()
{
    Matrix<double,Dynamic,Dynamic> a(2,2);
    a << 0,2,1,3;
    cout << "sum1(a) = " << sum1(a) << endl;            // ok
    cout << "sum2(a) = " << sum2(a) << endl;            // error
    cout << "sum2(a) = " << sum2<double>(a) << endl;    // ok
    return 0;
}

但我在编译时遇到错误:

$ clang++  -std=c++17 -I/usr/include/eigen3   eig2.cpp   -o eig2
eig2.cpp:33:29: error: no matching function for call to 'sum2'
    cout << "sum2(a) = " << sum2(a) << endl;            // error
                            ^~~~
eig2.cpp:19:1: note: candidate template ignored: could not match 'Ref' against
      'Matrix'
sum2(const Ref<const Matrix<T,Dynamic,Dynamic>> &m)
^
1 error generated.

有没有办法实现sum2,使其支持MatrixRef,并且不需要显式模板参数来使用它?

【问题讨论】:

    标签: c++ templates eigen


    【解决方案1】:

    原因

    template <typename T>
    T
    sum2(const Ref<const Matrix<T,Dynamic,Dynamic>> &m)
    

    不适用于Matrix&lt;T,Dynamic,Dynamic&gt; 是C++ 不能同时推断模板参数和进行类型转换(RefMatrix 是不同的类型,但它可以用 O(1 ) 努力)。

    允许您保留函数体的另一种选择(需要 C++11 或更高版本)是:

    template<typename Derived, typename T=typename Derived::Scalar>
    T sum3(const MatrixBase<Derived> &m) 
    

    如果你也想允许Array,你可以使用DenseBase,如果你想允许稀疏矩阵,你可以使用EigenBase

    但是,这并不等同于具有显式类型替换的 Ref 实现,因为如果 Derived 是一个表达式,它可能会在您的函数中被多次计算。

    另一种方法是写

    template <typename T>
    T
    sum_impl(const Ref<const Matrix<T,Dynamic,Dynamic>> &m)
    { /* here comes the actual implementation */ }
    
    template<typename Derived>
    typename Derived::Scalar sum4(const Eigen::MatrixBase<Derived>& m)
    {
        return sum_impl<typename Derived::Scalar>(m);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 2022-01-03
      相关资源
      最近更新 更多