3

我正在尝试执行矩阵求幂,但我不想复制/粘贴我的求幂函数,而宁愿使用类模板。问题是对于 boost 矩阵,要乘以矩阵,您使用prod函数(而不是operator*)。

似乎 g++ 无法找出我想要使用的模板。我用下面的代码得到的错误是

41:37: error: no matching function for call to 'my_pow(boost::numeric::ublas::matrix<int>&, int, <unresolved overloaded function type>)'

这是代码:

#include <iostream>
using namespace std;

#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>

typedef long long int64;

template <class T, class M> T my_pow(T b, int64 e, M mult)
{
  if (e == 1) return b;
  if (e % 2 == 1) return mult(b, my_pow(b, e - 1, mult));
  T tmp = my_pow(b, e / 2, mult);
  return mult(tmp, tmp);
}
template <class T> T my_pow(T b, int64 e) { return my_pow(b, e, multiplies<T>()); }

int main()
{
  using namespace boost::numeric::ublas;
  matrix<int> m(3, 3);
  for (unsigned i = 0; i < m.size1(); ++i)
    for (unsigned j = 0; j < m.size2(); ++j)
      m(i, j) = 3 * i + j;
  std::cout << m << std::endl;
  std::cout << my_pow(m, 2, prod) << std::endl;
}

有没有办法将 prod() 传递给 my_pow 以便模板解析?谢谢。

如果不清楚:b 是底数,e 是指数,my_pow 是计算 b^e

4

2 回答 2

2

您收到编译器错误的原因是函数有许多重载,prod并且在调用my_pow编译器时需要知道要提供哪一个。编译器无法推断您将 pow 函数应用于函数的第一个参数,因此在这里不知所措。

一种解决方案是将函数指针显式转换为正确的类型,但对于 uBlasprod重载,确定要转换为的正确类型可能非常复杂。

另一种解决方案是创建一个委托给适当的 pow 函数的多态函数对象。请注意,下面的实现做出了巨大的假设,即prod( m, m)返回与 m 相同类型的值(或可转换为 m 的值),但话又说回来,这是相同的假设,即您的my_powmake 和由此创建的临时变量很难避免功率e只能在运行时确定。

一个可以解决问题的多态函数类的示例:

struct my_prod
{
    template< typename M>
    M operator()( const M &left, const M &right) const
    {
        return prod( left, right);
    }

};

现在,如果您将呼叫更改my_pow为:

std::cout << my_pow(m, 2, my_prod()) << std::endl;

它应该工作(它对我有用)。

于 2012-02-01T20:57:50.897 回答
2

有两个问题。首先,prod是一个模板化的函数,所以不能只prod作为函数指针传递。相反,您需要prod<...>填写特定的模板参数。

但是在这种情况下,仍然无法解决您的问题,因为即使使用指定的模板参数,prod仍然有几个重载,编译器无法确定它应该使用哪一个。可以通过声明一个指定参数和返回类型的函数指针来解决这个问题。然而,由于ublas使用复杂的模板元编程,这将非常难看,我不推荐它。相反,我会编写一个包装函数prod来调用您想要的特定重载。这是一个非常通用的包装器,应该适用于任何 ublas 矩阵:

template <class E1, class E2> 
typename boost::numeric::ublas::matrix_matrix_binary_traits<
        typename E1::value_type, E1, 
        typename E2::value_type, E2>::result_type
my_prod(const boost::numeric::ublas::matrix_expression<E1>& e1, 
        const boost::numeric::ublas::matrix_expression<E1>& e2)
{
    return prod(e1, e2);
}

然后你可以my_pow这样调用my_prod

my_pow(m, 2, my_prod<matrix<int>, matrix<int> >)

只是为了好玩,这里是你需要传递的函数指针声明来解析模板参数和重载。这声明了一个名为的函数指针prod_ptr,它指向您想要的特定重载prod

matrix_matrix_binary_traits<matrix<int>::value_type, matrix<int>, matrix<int>::value_type, matrix<int> >::result_type 
    (*prod_ptr)(const matrix_expression<matrix<int> >&, const matrix_expression<matrix<int> >&) = 
    &prod<matrix_matrix_binary_traits<matrix<int>::value_type, matrix<int>, matrix<int>::value_type, matrix<int> >::result_type, matrix<int>, matrix<int> >;

然后你就可以my_pow使用函数指针调用:

my_pow(m, 2, prod_ptr);
于 2012-02-01T20:59:06.643 回答