`
zhangyafei_kimi
  • 浏览: 261634 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

一个STL风格的动态二维数组

阅读更多

#ifndef __KIMI_BOOST_ARRAY2
#define __KIMI_BOOST_ARRAY2


#pragma once
#include <cstddef> //size_t
#include <exception>//exception
#include <iterator>//random_access_iterator_tag,reverse_iterator
namespace kimi_boost
{

template <class T> class array2;//forward declaration


//iterator for class array2
template <class T,class Ref,class Ptr>
struct __M_array2_iterator
{
typedef std::random_access_iterator_tag iterator_category;
typedef T value_type;
typedef std::ptrdiff_t difference_type;
typedef Ptr pointer;
typedef Ref reference;

typedef __M_array2_iterator self;


std::size_t m;//index1
std::size_t n;//index2
array2<T>* m_pArray;//pointer to current array2 object

__M_array2_iterator():m(0),n(0),m_pArray(0){}

__M_array2_iterator(std::size_t m1, std::size_t n1, array2<T>* pArray)
:m(m1),n(n1),m_pArray(pArray){}

__M_array2_iterator(const __M_array2_iterator& y)
:m(y.m),n(y.n),m_pArray(y.m_pArray){}

reference operator*()const{return m_pArray->at(m,n);}
pointer operator->()const{return &(this->operator *());}

//necessary operators for a bidirectional iterator
self& operator++()
{
if(n < m_pArray->size2()-1) ++n;
else if (n == m_pArray->size2()-1 && m < m_pArray->size1()-1){n=0;++m;}
else n=m_pArray->size2();//pass the last element : end
return *this;
}
self operator++(int)
{
self temp=*this;
++*this;
return temp;
}
self& operator--()
{
if(n > 0) --n;
else if (n == 0 && m > 0){n=m_pArray->size2()-1;--m;}
return *this;
}
self operator--(int)
{
self temp=*this;
--*this;
return temp;
}
bool operator==(const self& x)const
{
return m_pArray==x.m_pArray && m==x.m && n==x.n;
}
bool operator!=(const self& x)const
{
return !operator ==(x);
}


//necessary operators for a random access iterator
difference_type operator-(const self& x)const
{
return difference_type( (m-x.m)*m_pArray->size2() + n-x.n );
}

self& operator += (difference_type x)
{
difference_type size2=m_pArray->size2();
difference_type total = n+x;
difference_type new_m = static_cast<difference_type>(m) + total/size2;
difference_type new_n = total%size2;

if( new_m >= static_cast<difference_type>(m_pArray->size1()) )//pass end(),and restrict to end()
{
m=m_pArray->size1()-1;
n=m_pArray->size2();
}
else if(new_m <0)//precede begin(),and restrict to begin()
{
m=0;
n=0;
}
else
{
m = new_m;
n = new_n;
}
return *this;
}
self operator + (difference_type n)const
{
self temp = *this;
return temp += n;
}
self& operator -= (difference_type n)
{
return *this += -n;
}
self& operator - (difference_type n)
{
self temp = *this;
return temp -= n;
}
bool operator<(const self& x)const
{
if(m<x.m) return true;
else if(m==x.m && n<x.n) return true;
else return false;
}

};

//a 2-dimension array
template <class T>
class array2
{
public:
typedef T value_type;
typedef __M_array2_iterator<T,T&,T*> iterator;
typedef __M_array2_iterator<T,const T&,const T*> const_iterator;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef std::reverse_iterator<iterator> reverse_iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;


private:
//Array Index Out Of Bounds Exception
struct ArrayIndexOutOfBoundsException : public std::exception
{
ArrayIndexOutOfBoundsException(const char *const& what):exception(what){}
};


//a proxy class that represents a 1-dimension array
class array1
{
public:
array1():m_ptr(0) , m_size(0){}

~array1()
{
if(m_ptr)
{
delete[] m_ptr;
m_ptr=0;
}
}

//initialize
void init(size_type N)
{
//delete []m_ptr;
m_ptr = new T[N];
m_size = N;
}

array1(const array1&);//ban copy ctor
array1& operator=(const array1&);//ban assignment

reference operator [](size_type N){return m_ptr[N];}
const_reference operator [](size_type N) const{return m_ptr[N];}

size_type size() const{return m_size;}
private:
T* m_ptr;
size_type m_size;
};

private:
array1* m_pCon;
size_type m_size;

//bounds check
void _M_init_proxys(size_type M,size_type N)
{
for(size_type i=0 ; i<M ; ++i)
m_pCon[i].init(N);
}
void _M_bounds_check(size_type M,size_type N) const
{
if(M >= m_size && N>=m_pCon[0].size())
throw ArrayIndexOutOfBoundsException("Array Index Out Of Bounds");
}
public:
array2():m_pCon(0),m_size(0){}

array2(size_type M, size_type N):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
}

~array2()
{
if(m_pCon && m_size)
{
delete[] m_pCon;
m_pCon=0;
}
}

array2(size_type M , size_type N , array2<T>& a):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
difference_type num2 = a.size();
difference_type num1 = M*N;
std::copy(a.begin(), (num1>=num2)?a.end():(a.begin()+num1) ,begin());
}

array2(size_type M , size_type N , iterator f , iterator l):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
difference_type num2 = std::distance(f,l);
difference_type num1 = M*N;
std::copy(f, (num1>=num2)?l:(f+num1) ,begin());
}

array2(const array2<T>& a)
{
m_pCon = new array1[a.m_size];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.m_pCon[0].size());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=a[i][j];
}
m_size=a.m_size;
}


array2<T>& operator = (const array2<T>& a)
{
if(&a != this)
{
delete []m_pCon;
m_pCon = new array1[a.m_size];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.m_pCon[0].size());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=a[i][j];
}
m_size=a.m_size;
}
return *this;
}

//retrieve the total size
size_type size()const
{return size1()*size2();}
//retrieve the first dimension's size
size_type size1()const
{return m_size;}
//retrieve the second dimension's size
size_type size2()const
{return m_pCon[0].size();}

//resize the array and keep the previous content in the array
void resize(size_type m,size_type n)
{
array1* newPlace=new array1[m];
for(size_type i=0 ; i<m ; ++i)
newPlace[i].init(n);

for(size_type i=0 ; i<std::min(m,m_size) ; ++i)
for(size_type j=0 ; j<std::min(n,m_pCon[0].size()) ; ++j)
newPlace[i][j] = m_pCon[i][j];
delete [] m_pCon;
m_pCon = newPlace;
m_size = m;
}


array1& operator [] (size_type m){return m_pCon[m];}
const array1& operator [] (size_type m) const{return m_pCon[m];}

reference at(size_type m,size_type n) { _M_bounds_check(m,n); return m_pCon[m][n]; }
const_reference at(size_type m,size_type n) const { _M_bounds_check(m,n); return m_pCon[m][n]; }

void assign (const_reference value)
{
std::fill_n(begin(),size(),value);
}

void swap(array2<T>& y)
{
std::swap(m_pCon , y.m_pCon);
std::swap(m_size , y.m_size);
}

iterator begin() { return iterator(0,0,this); }
const_iterator begin() const { return const_iterator(0,0,this); }
iterator end() { return iterator(size1()-1,size2(),this); }
const_iterator end() const { return const_iterator(size1()-1,size2(),this); }

reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
reverse_iterator rend() { return reverse_iterator(begin()); }
const_reverse_iterator rend() const {return const_reverse_iterator(begin());}

reference front() { return at(0,0); }
const_reference front() const {return at(0,0);}
reference back() { return at(size1()-1,size2()-1); }
const_reference back() const { return at(size1()-1,size2()-1); }


//member templates
template <class T2>
array2(const array2<T2>& a)
{
m_pCon = new array1[a.size1()];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.size2());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=static_cast<T>(a[i][j]);
}
m_size=a.size1();
}

template <class T2>
array2<T>& operator = (const array2<T2>& a)
{
delete []m_pCon;
m_pCon = new array1[a.size1()];
for(size_type i=0 ; i<a.size1() ; ++i)
{
m_pCon[i].init(a.size2());
for(size_type j=0 ; j<a.size2() ; ++j)
m_pCon[i][j]=static_cast<T>(a[i][j]);
}
m_size=a.size1();
return *this;
}

template <class T2>
void swap(array2<T2>& y)
{
//unfinished
}

template<class InputIterator>
array2(size_type M , size_type N , InputIterator f , InputIterator l):m_pCon(new array1[M]) , m_size(M)
{
_M_init_proxys(M,N);
difference_type num2 = std::distance(f,l);
difference_type num1 = M*N;
std::copy(f, (num1>=num2)?l:(f+num1) ,begin());
}
};

//relative global comparison functiaon
template<class T>
bool operator== (const array2<T>& x, const array2<T>& y)
{
if(x.size1() != y.size1() || x.size2() != y.size2() ) return false;
array2<T>* px = const_cast< array2<T>* >(&x);
array2<T>* py = const_cast< array2<T>* >(&y);
return std::equal (px->begin(), px->end(), py->begin());
}

template<class T>
bool operator< (const array2<T>& x, const array2<T>& y)
{
array2<T>* px = const_cast< array2<T>* >(&x);
array2<T>* py = const_cast< array2<T>* >(&y);
return std::lexicographical_compare(px->begin(),px->end(),py->begin(),py->end());
}

template<class T>
bool operator!= (const array2<T>& x, const array2<T>& y) {return !(x==y);}

template<class T>
bool operator> (const array2<T>& x, const array2<T>& y) {return y<x;}

template<class T>
bool operator<= (const array2<T>& x, const array2<T>& y) {return !(y<x);}

template<class T>
bool operator>= (const array2<T>& x, const array2<T>& y) {return !(x<y);}

// global swap()
template<class T>
inline void swap (array2<T>& x, array2<T>& y) {x.swap(y);}


}//end of namespace kimi_boost
#endif//__KIMI_BOOST_ARRAY2

接下来是例子程序

void array2_test()
{
kimi_boost::array2<float> f3(2,3);
kimi_boost::array2<float> f4(3,4);
f3[0][0]=456.3f;
f3[0][1]=46.9f;
f3[0][2]=45.9f;
f3[1][0]=-17.5f;
f3[1][1]=0.0f;
f3[1][2]=1.0f;

kimi_boost::array2<float> f10(3,2,f3.begin(),f3.end());
std::copy(f10.begin(),f10.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";

kimi_boost::array2<float> f11(3,5,f3);
std::copy(f11.begin(),f11.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
//f3[1] = f3[0]; //error

kimi_boost::array2<float> f1(f3);
kimi_boost::array2<float> f2;
f2=f3;
f4.assign(9.0f);
f3.swap(f4);
f3.swap(f4);

std::copy(f3.begin(),f3.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
std::sort(f3.begin(),f3.end());
std::copy(f3.begin(),f3.end(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";
std::copy(f3.rbegin(),f3.rend(),std::ostream_iterator<float>(std::cout," "));
std::cout<<"\r\n";

kimi_boost::array2<float> f6(f3);
std::cout<< (f6==f3) <<"\r\n";
std::cout<< (f6<f3) <<"\r\n";
f6[0][0]=666.666f;
std::cout<< (f6==f3) <<"\r\n";
std::cout<< (f3<f6) <<"\r\n";


vector<int> vi;
vi.assign(10,666);
kimi_boost::array2<int> ai(2,5,vi.begin(),vi.end());
std::copy(ai.begin(),ai.end(),std::ostream_iterator<int>(std::cout," "));
std::cout<<"\r\n";
}

不足之处多多

欢迎拍砖

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics