2015-05-21 1 views
0

Я пытаюсь изменить модуль линейной алгебры, чтобы избежать виртуальных виртуальных вещей. Пытаюсь использовать CRTP и шаблон выражения. Я пошел с чем-то базовым, чтобы проверить все это, и я не могу заставить его работать.CRTP и шаблон выражения Линейная алгебра

У меня есть 4 класса, скажем: Базовый класс CRTP, здесь Mathbase

template <typename Derived> 
class Mathbase 
{ 
public: 
using T = typename dense_traits<Derived>::T; 

    Derived& derived() { return static_cast<Derived&>(*this); } 
    const Derived& derived() const { return static_cast<const Derived&>(*this); } 

    T& coeff(std::size_t row, std::size_t col) { return derived().coeff(row, col); } 
    const T& coeff(std::size_t row, std::size_t col) const { return derived().coeff(row, col); } 
    T& coeff(std::size_t index) { return derived().coeff(index); } 
    const T& coeff(std::size_t index) const { return derived().coeff(index); } 
}; 

Затем Densebase, в котором я реализует такие функции, как транспозиции, определитель, и т.д.:

template <typename Derived> 
class Densebase : public Mathbase<Derived> 
{ 
public: 

using Submat = Subview<Derived, dense_traits<Derived>::M-1, dense_traits<Derived>::N-1>; 
using ConstSubmat = const Subview<const Derived, dense_traits<Derived>::M-1, dense_traits<Derived>::N-1>; 

    Submat sub(std::size_t row, std::size_t col) { return Submat(derived(), row, col); } 
    ConstSubmat sub(std::size_t row, std::size_t col) const { return ConstSubmat(derived(), row, col); } 
}; 

Примечание что он объявляет два типа, которые делают ссылки на родительскую матрицу (коматрицу) . Тогда у меня есть класс Matrix, который реализует функции коэффи- циента путем доступа к его памяти:

template <typename T, std::size_t M, std::size_t N> 
class Matrix : public Densebase<Matrix<T,M,N>> 
{ 
    // nothing fancy 
}; 

Теперь две вещи не работают:

  • Я реализовал определитель помощника, который использует расширение Лаплас (вычисления совместно матричные детерминанты и суммируя их, к сожалению, она не смогла составить

    template <typename Derived, std::size_t N> 
    struct det_helper 
    { 
        static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense) 
        { 
        typename dense_traits<Derived>::T det = 0; 
        // Laplace expansion 
        for (std::size_t i = 0; i < N; ++i) 
         det += ((i & 1) ? -1 : 1)*dense.coeff(0,i)*det_helper::run(dense.sub(0,i)); 
    
        return det; 
        } 
    }; 
    
    template <typename Derived> 
    struct det_helper<Derived, 2> 
    { 
        static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense) 
        { 
        return dense.coeff(0,0)*dense.coeff(1,1) - dense.coeff(0,1)*dense.coeff(1,0); 
        } 
    }; 
    

И называется так:

T determinant() const 
{ 
    return det_helper<Derived, dense_traits<Derived>::M>::run(derived()); 
} 
  • Вторая проблема заключается в том, что я реализовал перегрузку на << stream operator, которая отлично работает на матрице, но сбой на stream << matrix.sub(0,0); без ввода функции.

Вот полный код загружен на PASTEBIN

И выход ошибка, спросил:

main.cpp: In instantiation of 'static typename dense_traits<T>::T det_helper<Derived, N>::run(const Densebase<Derived>&) [with Derived = Matrix<float, 3ul, 3ul>; long unsigned int N = 3ul; typename dense_traits<T>::T = float]': 
main.cpp:68:62: required from 'typename Densebase<Derived>::base::T Densebase<Derived>::determinant() const [with Derived = Matrix<float, 3ul, 3ul>; typename Densebase<Derived>::base::T = float]' 
main.cpp:159:30: required from here 
main.cpp:33:65: error: no matching function for call to 'det_helper<Matrix<float, 3ul, 3ul>, 3ul>::run(Densebase<Matrix<float, 3ul, 3ul> >::ConstSubmat)' 
     det += ((i & 1) ? -1 : 1)*dense.coeff(0,i)*det_helper::run(dense.sub(0,i)); 
                   ^
main.cpp:28:51: note: candidate: static typename dense_traits<T>::T det_helper<Derived, N>::run(const Densebase<Derived>&) [with Derived = Matrix<float, 3ul, 3ul>; long unsigned int N = 3ul; typename dense_traits<T>::T = float] 
    static inline typename dense_traits<Derived>::T run(const Densebase<Derived>& dense) 
               ^
main.cpp:28:51: note: no known conversion for argument 1 from 'Densebase<Matrix<float, 3ul, 3ul> >::ConstSubmat {aka const Subview<const Matrix<float, 3ul, 3ul>, 2ul, 2ul>}' to 'const Densebase<Matrix<float, 3ul, 3ul> >&' 
+0

Как вы можете различать две перегрузки 'Densebase :: sub'? У них такая же подпись, нет? – Carlton

+0

Кроме того, когда вы говорите, что он не компилируется, какая ошибка вы получаете? – Carlton

ответ

1

Я не знаю, что ваша ошибка (ы) компиляции есть, но перегруженные Mathbase::coeff и Densebase::sub имеют одну и ту же подпись (имена и типы аргументов), которые не будут компилироваться. Вы не можете перегружать функцию только своим типом возврата, который, похоже, вы пытаетесь сделать.

+0

Функции Nope thoses компилируются, потому что один из них const, другой isnt, я загрузил код, так как он довольно длинный, вы можете получить полный обзор. – hrkz

+0

Простите, я пропустил это. Ты прав. – Carlton