Динамический N-мерный массив
От: WolfHound  
Дата: 28.11.02 14:59
Оценка:
#pragma once
template<class T_C, int T_DIM>class T_Array
{
    T_C* m_Data;
    int m_index[T_DIM+1];
    int m_shift[T_DIM+1];
    template<int T_PDIM>class Proxy
    {
        T_C* m_data;
        int* m_shift;
        int* m_index;
    public:
        Proxy(T_C* data, int* shift, int* index)
            :m_data(data)
            ,m_shift(shift)
            ,m_index(index)
        {}
        Proxy<T_PDIM-1> operator[](int i)
        {
            if(i<0||i>=m_index[0])throw InvalidIndex();
            return Proxy<T_PDIM-1>(m_data+m_shift[0]*i, &m_shift[1], &m_index[1]);
        }
    };
    template<>class Proxy<1>
    {
        T_C* m_data;
        int* m_index;
    public:
        Proxy<1>(T_C* data, int* shift, int* index)
            :m_data(data)
            ,m_index(index)
        {}
        T_C& operator[](int i)
        {
            if(i<0||i>=m_index[0])throw InvalidIndex();
            return *(m_data+i);
        }
    };
public:
    class InvalidIndex{};
    T_Array(int* index)
        :m_Data(0)
    {
        for(int i=0;i<T_DIM;i++)
            if((m_index[i]=m_shift[i]=index[i])<=0)throw InvalidIndex();
        m_index[T_DIM]=m_shift[T_DIM]=0;
        for(int i=T_DIM-2;i>=0;i--)
            m_shift[i]*=m_shift[i+1];
        m_Data=new T_C[m_shift[0]];
    }
    ~T_Array()
    {
        delete[] m_Data;
    }
    Proxy<T_DIM-1> operator[](int i)
    {
        if(i<0||i>=m_index[0])throw InvalidIndex();
        return Proxy<T_DIM-1>(m_Data+m_shift[1]*i, &m_shift[2], &m_index[1]);
    }
};

Пример использования
#include "stdafx.h"
#include "T_Array.h"
int _tmain(int argc, _TCHAR* argv[])
{
    int x=2;
    int y=3;
    int z=3;
    int ind[]={x, y, z};
    T_Array<int, 3> arr(ind);//долбаные плюсы
    //Так не дают T_Array<int, 3> arr({x, y, z});
    arr[1][2][-1]=10;//throw InvalidIndex
    x=arr[1][2][2];
    return 0;
}
... << RSDN@Home 1.0 alpha 12 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: Динамический N-мерный массив
От: Кодт Россия  
Дата: 28.11.02 16:24
Оценка: 15 (1)
Здравствуйте, WolfHound, Вы писали:

<>

WH>Пример использования

WH>int _tmain(int argc, _TCHAR* argv[])
WH>{
WH>    int x=2;
WH>    int y=3;
WH>    int z=3;
WH>    int ind[]={x, y, z};
WH>    T_Array<int, 3> arr(ind);//долбаные плюсы


Долбаные плюсы позволяют объехать это такими способами.
1) эллипсис
TArray::TArray(int index1, ...)
{
  va_list indices;
  va_start(indices, index1);
  ...
}

но это небезопасно

2) объект-хелпер
T_Array<int,3> arr( Dimensions<3>() [2][3][3] );

// Dimensions<N>::operator Dim<N,N>& ();
// Dim<N,K-1> Dim<N,K>::operator[](size_t value_of_dimension)
Перекуём баги на фичи!
Re[2]: Динамический N-мерный массив
От: WolfHound  
Дата: 28.11.02 19:38
Оценка:
Здравствуйте Кодт, Вы писали:

Как ты думаешь? если я написал этот шаблон то сколько вариантов обьезда этого я смогу придумать?
Мне просто не понятно почему для простых вещей требуются сложные решения.
Ибо сделать такой синтаксис допустимым ни чего не стоит
T_Array<int, 3> arr({x, y, z});

нужно всеголишь создать анонимный массив на стеке.
... << RSDN@Home 1.0 alpha 12 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re: А мне так больше нравится:
От: Atilla Россия  
Дата: 29.11.02 09:21
Оценка:
typedef std::vector<int> IntegerVector;

template<class T>
class array: public std::vector<T>
{
    typedef std::vector<T> _Mybase;
    IntegerVector m_dims;
public:
    typedef typename _Mybase::allocator_type allocator_type;
    typedef typename _Mybase::size_type size_type;
    typedef typename _Mybase::difference_type difference_type;
    typedef typename _Mybase::pointer pointer;
    typedef typename _Mybase::const_pointer const_pointer;
    typedef typename _Mybase::reference reference;
    typedef typename _Mybase::const_reference const_reference;
    typedef typename _Mybase::value_type value_type;
    typedef typename _Mybase::iterator iterator;
    typedef typename _Mybase::const_iterator const_iterator;
    typedef typename _Mybase::reverse_iterator reverse_iterator;
    typedef typename _Mybase::const_reverse_iterator const_reverse_iterator;

    array():
        std::vector<T>(), m_dims(){}

    array(const IntegerVector& d):
        std::vector<T>(), m_dims()
    {
        resize(d);
    }

    array(const IntegerVector& d, const value_type& val):
        std::vector<T>(), m_dims()
    {
        resize(d, val);
    }

    ~array(){}

    void resize(const IntegerVector& d, const value_type& val=value_type(0))
    {
        m_dims=d;
        _Mybase::resize(std::accumulate(d.begin(), d.end(), 1, std::multiplies<Integer>()), val);
    }

    const IntegerVector& dims() const {return m_dims;}

    size_type index(const IntegerVector& I) const
    {
        assert(I.size()==m_dims.size());
        for(size_type dim=0;dim<I.size();dim++)
        {
            assert(I[dim]<m_dims[dim]);
        }
        size_type n=I[0], m=m_dims[0];
        for(size_type i=1;i<I.size();i++)
        {
            n+=I[i]*m;
            m*=m_dims[i];
        }
        return n;
    }

    size_type index(const std::vector<size_type>& I) const
    {
        assert(I.size()==m_dims.size());
        for(size_type dim=0;dim<I.size();dim++)
        {
            assert(I[dim]<m_dims[dim]);
        }
        size_type n=I[0], m=m_dims[0];
        for(size_type i=1;i<I.size();i++)
        {
            n+=I[i]*m;
            m*=m_dims[i];
        }
        return n;
    }

    IntegerVector index(size_type I) const
    {
        assert(I<size());
        IntegerVector res(m_dims.size());
        for(size_type i=m_dims.size()-1;i>0;i--)
        {
            res[i]=I/m_dims[i-1];
            I%=m_dims[i-1];
        }
        res[0]=I;
        return res;
    }

    value_type operator[] (const IntegerVector& I) const
    {
        return _Mybase::operator[] (index(I));
    }

    reference operator[] (const IntegerVector& I)
    {
        return _Mybase::operator[] (index(I));
    }

    value_type operator[] (size_type I) const
    {
        return _Mybase::operator[] (I);
    }

    reference operator[] (size_type I)
    {
        return _Mybase::operator[] (I);
    }
};


Может тут, конечно, какой-нибудь наворот не реализован, но мне пока хватало
Кр-ть — с.т.
Re[2]: Не забываем уже существующие библиотеки (blitz++)
От: Anton V. Kolotaev  
Дата: 29.11.02 09:58
Оценка:
Здравствуйте, Atilla,

Не забываем уже существующие библиотеки (blitz++) и указываем, чем отличается свое творение от них.
Re[3]: Не забываем уже существующие библиотеки (blitz++)
От: Atilla Россия  
Дата: 29.11.02 10:05
Оценка:
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Не забываем уже существующие библиотеки (blitz++) и указываем, чем отличается свое творение от них.


Мне кроме этого шаблона ничего и не надо А в библиотеках наверняка еще куча всего ненужного валяется, а все это за собой таскать не охота. А чем лучше — это тем что со своим творением я могу делать что угодно (код править, свободно распространять и т.д.), а вот насчет библиотеки — неизвестно, надо лицензию читать. И не понятно еще где библиотека будет компилировться, а где нет. Этот же шаблон проверен MSC++, IC++, gcc, sunws.
Кр-ть — с.т.
Re[4]: Не забываем уже существующие библиотеки (blitz++)
От: Anton V. Kolotaev  
Дата: 29.11.02 10:19
Оценка:
Здравствуйте, Atilla, Вы писали:

AVK>>Не забываем уже существующие библиотеки (blitz++) и указываем, чем отличается свое творение от них.


A>Мне кроме этого шаблона ничего и не надо А в библиотеках наверняка еще куча всего ненужного валяется, а все это за собой таскать не охота. А чем лучше — это тем что со своим творением я могу делать что угодно (код править, свободно распространять и т.д.), а вот насчет библиотеки — неизвестно, надо лицензию читать. И не понятно еще где библиотека будет компилировться, а где нет. Этот же шаблон проверен MSC++, IC++, gcc, sunws.


Я не имел в виду, что надо обязательно использовать, и в этом ты прав. Однако поизучать используемые в них приемы оказывается весьма интересным занятием.
Re[5]: Не забываем уже существующие библиотеки (blitz++)
От: Atilla Россия  
Дата: 29.11.02 10:23
Оценка:
Здравствуйте, Anton V. Kolotaev, Вы писали:

AVK>Однако поизучать используемые в них приемы оказывается весьма интересным занятием.


Это верно. Но к счастью существует огромное количество библиотек с которыми можно работать только основательно изучив их код
Кр-ть — с.т.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.