2012-02-01 71 views
3

我试图执行矩阵求幂,但我不想复制/粘贴我的指数函数,而宁愿使用类模板。问题是对于增强矩阵来说,为了使矩阵相乘,可以使用prod函数(而不是operator*)。如何将boost矩阵prod()函数作为乘法函数传递?

似乎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

回答

2

为什么你所得到的编译器错误是,有是prod的大量重载的原因功能,并且在my_pow的调用中,编译器需要知道应该提供哪一个。编译器不能推断你将pow函数应用到你的函数的第一个参数,所以它在这里不知所措。

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

另一种解决方案是创建一个多态函数对象,该对象委托给相应的pow函数。请注意,下面的实现使得prod(m, m)返回一个与m相同类型的值的巨大假设(或者可转换为它的东西),但是再次,这与假设my_pow所做的假设相同,并且创建的临时对象很难如果功率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; 

它应该工作(它为我)。

2

有两个问题。首先,prod是一个模板化函数,因此您不能只将prod作为函数指针。相反,你需要通过prod<...>被填充到特定的模板PARAMATERS。在这种情况下仍然不会因为即使有指定的模板参数解决您的问题

然而,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); 
+0

由于一吨。给你upvote,但我最终独立使用了与dhavenith相同的解决方案,所以我给了他支票。尽管他对返回类型做出了假设,但考虑到您提供的更一般包装的复杂性,我认为这是可以原谅的。其他任何人都觉得有时候会提高方式来解决问题? – Brian 2012-02-02 15:13:27

+0

和upvote查找'matrix_matrix_binary_traits'。 – dhavenith 2012-02-03 15:50:53

相关问题