正文

我写的多维数组auto_array2008-02-19 00:08:00

【评论】 【打印】 【字体: 】 本文链接:http://blog.pfan.cn/rickone/32745.html

分享到:

练手的 [定义] auto_array<typename T, std::size_t dim, typename Allocator = _test_allocator<T> > a; 第一个参数是元素类型,第二个是最高维度,维度标记从0到dim-1,第三个是一个分配器 [重塑数组大小] reshape(std::size_t dim_index, std::size_t width, long start = 0); 第一个参数是指定第几维,第二个参数是指定该维的宽度,第三个参数是起始下标. 这个函数可以重叠使用,如 a.reshape(0,4);a.reshape(1,5); 等价于 a.reshape(0,4)(1,5); [operator[]操作] 和C语言的数组[]操作一样,没有任何不同,只是多了运行时越界检查. 测试代码(编译环境Dev C++(GCC)): #include <iostream>#include "auto_array.hpp" using namespace std; int main(int argc, char *argv[]){    auto_array<int,1> a;    a.reshape(0,5);    try {    a[0]=1;    a[0]+=2;    a[1]=3;    a[4]=a[0]*a[1];    }    catch(runtime_error &err)    {      cout<<err.what()<<endl;      system("PAUSE");      return 0;    }    //auto_array<int,2> a;    //a.reshape(0,4)(1,5);    //a[3][0]=1;    if(!a.empty())      cout<<"a is not null"<<endl;    cout<<a[0]<<endl        <<a[1]<<endl        <<a[2]<<endl;    cout<<a.size()<<endl        <<a.max_size()<<endl;    a=0;    if(!a)      cout<<"a is null now"<<endl;        system("PAUSE");    return EXIT_SUCCESS;} 下一步,设计一个和boost::multi_array类似的'生成器',以下是源码,版权所有: #ifndef AUTO_ARRAY#define AUTO_ARRAY #include <stdexcept> //test allocatortemplate<typename T>class _test_allocator{public:  static void* allocate(std::size_t n)  {    return malloc(n*sizeof(T));  }   static void deallocate(void* p, std::size_t /* __n */)  {    free(p);  }   static void* reallocate(void* __p, std::size_t /* old_sz */, std::size_t __new_sz)  {    return realloc(__p, __new_sz*sizeof(T));  }}; struct range_list{  long start;  std::size_t width;  std::size_t step;}; template<typename T, std::size_t dim, typename Allocator = _test_allocator<T> >class auto_array{public:  typedef T value_type;  typedef value_type* pointer;  typedef const value_type* const_pointer;  typedef value_type* iterator;  typedef const value_type* const_iterator;  typedef value_type& reference;  typedef const value_type& const_reference;  typedef size_t size_type;  typedef ptrdiff_t difference_type;    auto_array() : range_changed(false), data(0), length(0), max_sz(0)  {    for(std::size_t i=0;i<dim;++i)      rl[i].width=0;  }    template<std::size_t _dim>  class reshape_functor  {  public:    reshape_functor(range_list *prl) : rl(prl) {}    reshape_functor operator()(std::size_t dim_index, std::size_t width, long start = 0)    {      if(dim_index>=_dim)        throw(std::runtime_error("array reshape error: dimensionality too big"));      rl[dim_index].start=start;      rl[dim_index].width=width;      return *this;    }  private:    range_list *rl;  };    reshape_functor<dim>  reshape(std::size_t dim_index, std::size_t width, long start = 0)  {    range_changed=true;    return reshape_functor<dim>(rl)(dim_index,width,start);  }   template<typename _T, std::size_t _dim>  class index_functor  {  public:    index_functor(_T *pdata, const range_list *prl) : data(pdata), rl(prl) {}    index_functor<_T,_dim-1> operator[](long index)    {      if(index>=rl[0].start && index-rl[0].start<static_cast<long>(rl[0].width))        return index_functor<_T,_dim-1>(data+(index-rl[0].start)*rl[0].step,rl+1);      else        throw(std::runtime_error("array access error: out of bound"));    }  private:    _T *data;    const range_list *rl;  };    template<typename _T>  class index_functor<_T,0>  {  public:    index_functor(_T *pdata, const range_list *prl) : data(pdata) {}    operator _T(){ return data[0]; }        template<typename U>    _T& operator=(const U &other){ return data[0]=other; }        template<typename U>    _T& operator+=(const U &other){ return data[0]+=other; }        template<typename U>    _T& operator-=(const U &other){ return data[0]-=other; }        template<typename U>    _T& operator*=(const U &other){ return data[0]*=other; }        template<typename U>    _T& operator/=(const U &other){ return data[0]/=other; }        template<typename U>    _T& operator%=(const U &other){ return data[0]%=other; }        template<typename U>    _T& operator<<=(const U &other){ return data[0]<<=other; }        template<typename U>    _T& operator>>=(const U &other){ return data[0]>>=other; }        template<typename U>    _T& operator^=(const U &other){ return data[0]^=other; }        template<typename U>    _T& operator&=(const U &other){ return data[0]&=other; }        template<typename U>    _T& operator|=(const U &other){ return data[0]|=other; }      private:    _T *data;  };    index_functor<T,dim-1>  operator[](long index)  {    if(getready())      return index_functor<T,dim>(data,rl)[index];    else      throw(std::runtime_error("array access error: shape uninitialized"));  }    struct dummy{void nonnull(void){}};  typedef void (dummy::*safe_bool)(void);  operator safe_bool() {return data==0?0:&dummy::nonnull;}    bool empty() const {return data==0;}    size_type size() const { return length; }    size_type max_size() const { return max_sz; }    void clear()  {    if(data)    {      deallocate(data,max_sz);      data=0;      max_sz=0;    }  }    void operator=(int zero){ clear(); }    iterator begin() { return data; }  const_iterator begin() const { return data; }    iterator end() { return data+length; }  const_iterator end() const { return data+length; }  private:  pointer allocate(std::size_t n){ return static_cast<pointer>(Allocator::allocate(n)); }  void deallocate(pointer p, std::size_t sz){ Allocator::deallocate(static_cast<void*>(p),sz); }  pointer reallocate(pointer p, std::size_t _old_sz, std::size_t _new_sz){ return static_cast<pointer>(      Allocator::reallocate(static_cast<void*>(p),_old_sz,_new_sz)       ); }  bool getready(); private:  range_list rl[dim];  bool range_changed;  T* data;  std::size_t length;  std::size_t max_sz;}; template<typename T, std::size_t dim, typename Allocator>bool auto_array<T,dim,Allocator>::getready(){  if(range_changed)  {    std::size_t _new_length=1;    for(long i=dim-1;i>=0;--i)    {      _new_length*=rl[i].width;      rl[i].step = (i+1==dim?1:rl[i+1].step*rl[i+1].width);    }    if(_new_length>max_sz)    {      do{        max_sz = (max_sz==0?128:(max_sz<<1));      }while(_new_length>max_sz);      if(data)        data=reallocate(data,0,max_sz);      else        data=allocate(max_sz);    }    length=_new_length;    range_changed=false;  }  return length>0;} #endif // by rickone 2008/02/18

阅读(9201) | 评论(1)


版权声明:编程爱好者网站为此博客服务提供商,如本文牵涉到版权问题,编程爱好者网站不承担相关责任,如有版权问题请直接与本文作者联系解决。谢谢!

评论

loading...
您需要登录后才能评论,请 登录 或者 注册