c++ - 标量类型的特征模板

标签 c++ templates eigen

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

例如, 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并且不需要明确的模板参数来使用它?

最佳答案

原因

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

不适用于 Matrix<T,Dynamic,Dynamic>是 C++ 不能同时推导模板参数和进行类型转换( Ref 是与 Matrix 不同的类型,但它可以用 O(1) 的努力来构建)。

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

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

如果你想允许 Array同样,您可以使用 DenseBase ,如果你想允许稀疏矩阵,你可以使用 EigenBase .

但是,这不等同于 Ref具有显式类型替换的实现,因为 if 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);
}

关于c++ - 标量类型的特征模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58461309/

相关文章:

windows - QtCreator 无法打开包含文件 (Windows)

c++ - 按常量偏移多段线

c++ - 从模板调用类保护方法

silverlight - 从代码设置silverlight模板?

c++ - 带有 const 引用的 std::remove_const

c++ - 将 Eigen::SparseMatrix 转换为 cuSparse,反之亦然

C++ - DirectSoundBuffer 在特定位置停止播放 - 无通知

c++ - 如果编译器不支持,将可变参数传递给 lambda 表达式的解决方法

c++ - c/c++ 将位置相关对象转换为位置无关对象

c++ - 在 MSVC 中强制未对齐的位域打包