带有 Armadillo 的 C++ 函数模板

Function templates in C++ with Armadillo

我正在使用犰狳线性代数库编写一些函数模板,但遇到了一些错误。我仍在学习 C++ 及其方面,因此非常感谢任何可能的解决方案。我的大部分功能如下所示,

template<typename T1>
void some_function(const Mat<T1> & p)
{
    unsigned int n = p.n_rows;
    // do some stuffs...
    // ....
}

我的主要功能包括:

Mat<double> A = ones<Mat<double>>(4,4);
int a(2);
some_function(A);  // runs perfectly
some_function(a*A); // compilation error as follows

test_function.hpp:35:8: note: template argument deduction/substitution failed:
test.cpp:22:17: note: ‘arma::enable_if2<true, const arma::eOp<arma::Mat<double>, arma::eop_scalar_times> >::result {aka const arma::eOp<arma::Mat<double>, arma::eop_scalar_times>}’ is not derived from ‘const arma::Mat<eT>’
some_function(a*A);

如果我改变函数如下:

template<typename T1>
void some_function(const T1 & p)
{
    unsigned int n = p.n_rows;
    // do some stuffs...
    // ....
}

然后给出编译错误如下:

test_function.hpp: In instantiation of ‘bool some_function(const T1&) [with T1 = arma::eOp<arma::Mat<double>, arma::eop_scalar_times>]’:
test.cpp:22:17:   required from here
test_function.hpp:37:26: error: ‘const class arma::eOp<arma::Mat<double>, arma::eop_scalar_times>’ has no member named ‘n_rows’
 unsigned int n = p.n_rows;

但是非模板函数可以完美运行,比如

void some_function(const Mat<double> & p)
{
    unsigned int n = p.n_rows();
    // do some stuffs...
    // ....
}

有什么解决办法吗??

我认为有了这些帮手:

template <typename T>
const Mat<T>& as_Mat(const Mat<T>& m) {return m;}

template<typename T1, typename eop_type>
Mat<typename T1::elem_type> as_Mat(const eOp<T1, eop_type>& X)
{
    return {X};
}

你可以写:

template<typename T>
void some_function(const T & p)
{
    const auto& mat = as_mat(p);
    unsigned int n = mat.n_rows();
    // do some stuffs...
    // ....
}

使用.eval()成员函数强制将Armadillo表达式转换为矩阵。

然后您可以使用 .eval() 的结果作为函数的输入。例如:

mat A(10,20,fill::randu);
mat B(10,20,fill::randu);

some_function( (A+B).eval() );

另请注意,Mat class 没有名为 n_rows() 的成员函数。相反,它有一个名为 n_rows 的只读变量。例如:

unsigned int n = X.n_rows;

Jarod42的post之后,我花了一些时间在这件事上,并找到了解决这个问题的另一种可能的方法,非常类似于 Jarod42的一个。我正在回复它作为任何可能像我一样陷入同样问题的人的答案。 我只是更改了 Jarod42 已经编写的第二个 as_Mat 函数。

template <typename T>
const Mat<T>& as_Mat(const Mat<T>& m) {return m;}


template<typename T>
Mat<typename T::elem_type> as_Mat(const T& X)
{
    return {X};
}

并且所有用户定义的函数都将像以前一样包含一行。

template<typename T>
void some_function(const T & X)
{
    const auto& Y = as_Mat(X);
    // do some stuffs with Y...
    // ....
} 

这样任何延迟的评估都会被转换成矩阵,例如。 A+B, A*B, i*A (i = int, complex<>,double...) 等等等等等等

虽然我不确定代码的性能,而且正如 mtall 提到的 .eval() 函数一样,此修复对于构建模板化非常有帮助使用 Armadillo 的图书馆,图书馆用户不需要每隔一段时间输入 .eval()。再次感谢大家的帮助和关注。