Шаблоны классов наследников и вложенные типы.
От: Razard Россия  
Дата: 24.05.15 11:31
Оценка:
Есть базовый шаблонный класс матриц MatrixBase и несколько шаблонных наследников MatrixDense, MatrixSparse и т.д.:

template <int _rows, int _cols, typename type> class MatrixBase
{
public:
    type* _pData;
    int _r;
    int _c;

    void _reset(void)
    {
        _pData = 0;
        _r = 0;
        _c = 0;
    }

    void _flush(void)
    {
        try { delete[] _pData; } catch(...) {};
    }

    bool _alloc(int rows, int cols)
    {
        if (rows*cols==0) return false;
        try
        {
            _pData = new type[rows*cols];
        }
        catch(...)
        {
            return false;
        }
        _r = rows;
        _c = cols;
        return true;
    }

    MatrixBase(void)
    {
        _reset();
    }

    ~MatrixBase(void)
    {
        _flush();
        _reset();
    }

    const type& _get(int r, int c) const
    {
        return _pData[_c*r+c];
    }

    type& _get(int r, int c)
    {
        return _pData[_c*r+c];
    }

    template <typename t>
    void _set(int r, int c, const t& val)
    {
        _pData[_c*r+c] = val;
    }

    template <int _rowsM, int _colsM>
    void set(const MatrixBase<_rowsM,_colsM,type>& M)
    {
        for (int r = 0; r<_r; r++)
            for (int c = 0; c<_c; c++)
                _set(r,c, M._get(r,c));
    }

    template <int _rowsM, int _colsM>
    void operator=(const MatrixBase<_rowsM,_colsM,type>& M)
    {
        set(M);
    }

};

template <int _rows, int _cols, typename type> class MatrixDense : public MatrixBase<_rows,_cols,type>
{
public:
    MatrixDense(void) { _alloc(_rows, _cols); }
    MatrixDense(int rows, int cols) { _alloc(rows, cols); }
    ~MatrixDense(void) {}
};

template <int _rows, int _cols, typename type> class MatrixSparse : public MatrixBase<_rows,_cols,type>
{
public:
    MatrixSparse(void) { _alloc(_rows, _cols); }
    MatrixSparse(int rows, int cols) { _alloc(rows, cols); }
    ~MatrixSparse(void){}
};


В простых случаях все работает:
MatrixDense<3,3,float> D;
MatrixSparse<3,3,float> S;
D.set(S);


В более сложном случае с одинаковыми типами элементам-матрицами тоже все работает:
MatrixDense<0,0,MatrixDense<3,3,float>> D(4,4);
MatrixSparse<0,0,MatrixDense<3,3,float>> S(4,4);
D.set(S);


Однако, если типы элементов-матриц различны — не собирается:
MatrixDense<0,0,MatrixDense<3,3,float>> D(4,4);
MatrixDense<0,0,MatrixSparse<3,3,float>> S(4,4);
D.set(S);


Пишет:

Error: no instance of function template "MatrixDense<_rows,_cols,type>::set [with _rows=0, _cols=0, type=MatrixDense<3,3,float> ]" matched the argument list
argument types are: (MatrixDense<0,0,MatrixSparse<3,3,float>>)
object type is: MatrixDense<0,0,MatrixDense<3,3,float>>


Понятно, что конечные типы по факту различны, но они наследуются от общего предка, и как в первом случае все работает. Почему в последнем не работает?
Re: Шаблоны классов наследников и вложенные типы.
От: uzhas Ниоткуда  
Дата: 24.05.15 12:14
Оценка: 2 (1)
Здравствуйте, Razard, Вы писали:


R> const type& _get(int r, int c) const

R> {
R> return _pData[_c*r+c];
R> }

R> type& _get(int r, int c)

R> {
R> return _pData[_c*r+c];
R> }

R> template <typename t>

R> void _set(int r, int c, const t& val)
R> {
R> _pData[_c*r+c] = val;
R> }

R> template <int _rowsM, int _colsM>

R> void set(const MatrixBase<_rowsM,_colsM,type>& M)
R> {
R> for (int r = 0; r<_r; r++)
R> for (int c = 0; c<_c; c++)
R> _set(r,c, M._get(r,c));
R> }

R>Однако, если типы элементов-матриц различны — не собирается:

R>
R>MatrixDense<0,0,MatrixDense<3,3,float>> D(4,4);
R>MatrixDense<0,0,MatrixSparse<3,3,float>> S(4,4);
R>D.set(S);
R>


важный код я оставил
проблема в методе set, который требует совпадение типов данных внутри матрицы
у матрицы D элементы имеют тип MatrixDense<3,3,float>
у матрицы S элементы имеют другой тип MatrixSparse<3,3,float>

если мы хотим поддержать копирование разнородных элементов, то сигнатуру метода надо изменить:
template <int _rowsM, int _colsM, typename _typeM>
    void set(const MatrixBase<_rowsM,_colsM,_typeM>& M)
    {
        for (int r = 0; r<_r; r++)
            for (int c = 0; c<_c; c++)
                _set(r,c, M._get(r,c));
    }


но в этом случае нам надо поддержать копирование из типа MatrixSparse<3,3,float> в MatrixDense<3,3,float> (надо написать соответствующие operator= )

ps. дизайн классов и реализация в плачевном состоянии, надо проработать их аккуратнее
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.