2012-02-01 2 views
3

Я пытаюсь выполнить экспоненцию матрицы, но я не хочу копировать/вставлять мою функцию экспоненции и скорее использовать шаблоны классов. Проблема в том, что для матриц форсирования, для умножения матриц, вы используете функцию prod (вместо operator*).Как передать функцию prod() матрицы boost как функцию умножения?

Похоже, что 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; 
} 

Есть ли способ передать тычок() для my_pow поэтому шаблон решает? Благодарю.

Это случае это не ясно: б является основой, е является показателем, и my_pow является вычислением Ь^E

ответ

2

причины, почему вы получаете ошибку компилятора является то, что есть много перегрузок prod и при вызове my_pow компилятор должен знать, какой из них следует предоставить. Компилятор не может вывести, что вы будете применять функцию pow к первому аргументу вашей функции, поэтому здесь это не работает.

Одним из решений было бы явно направить указатель на нужный тип, но для uBlas prod перегрузки, определяющие правильный тип для отливки, могут быть довольно сложными.

Другим решением является создание объекта полиморфной функции, который делегирует соответствующую функцию 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<...> с конкретными параметрами шаблона.

Однако в этом случае это еще не устранит проблему, потому что даже с указанными параметрами шаблона 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

Благодаря тонну. Дал вам верх, но я оказался независимо тем же решением, что и dhavenith, поэтому дал ему чек. Несмотря на то, что он делает предположения о типах возврата, я думаю, что это простительно, учитывая сложность более общей обертки, которую вы представили. Кто-нибудь еще чувствует, что форсированный способ слишком часто компромиссен? – Brian

+0

и upvote для поиска 'matrix_matrix_binary_traits'. – dhavenith

 Смежные вопросы

  • Нет связанных вопросов^_^