ViennaGrid - The Vienna Grid Library  2.1.0
viennagrid/storage/static_array.hpp
Go to the documentation of this file.
00001 #ifndef VIENNAGRID_STORAGE_STATIC_ARRAY_HPP
00002 #define VIENNAGRID_STORAGE_STATIC_ARRAY_HPP
00003 
00004 /* =======================================================================
00005    Copyright (c) 2011-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                      ViennaGrid - The Vienna Grid Library
00011                             -----------------
00012 
00013    License:      MIT (X11), see file LICENSE in the base directory
00014 ======================================================================= */
00015 
00016 #include <cassert>
00017 #include <cstddef>
00018 #include <iterator>
00019 
00024 namespace viennagrid
00025 {
00027   template<typename T, int N>
00028   class static_array
00029   {
00030     T elements_[N];    // fixed-size array of elements of type T
00031 
00032   public:
00033     // type definitions
00034     typedef T              value_type;
00035     typedef T*             pointer;
00036     typedef const T*       const_pointer;
00037 
00038     typedef T&             reference;
00039     typedef const T&       const_reference;
00040     typedef std::size_t    size_type;
00041     typedef std::ptrdiff_t difference_type;
00042 
00043     class const_iterator;
00044 
00045     static_array()
00046     {
00047       for (std::size_t i=0; i<static_cast<size_t>(N); ++i)
00048         elements_[i] = T();
00049     }
00050 
00051     // random access iterator: http://www.cplusplus.com/reference/std/iterator/RandomAccessIterator/
00052     class iterator
00053     {
00054       friend class const_iterator;
00055     public:
00056 
00057       typedef std::size_t difference_type;
00058       typedef typename static_array::value_type value_type;
00059       typedef typename static_array::pointer pointer;
00060       typedef typename static_array::reference reference;
00061       typedef typename static_array::const_reference const_reference;
00062       typedef std::random_access_iterator_tag iterator_category;
00063 
00064       // default-constructable
00065       iterator() : ptr_(0) {}
00066 
00067       // copy- and copy-constructable
00068       iterator(const iterator & it) : ptr_(it.ptr_) {}
00069       iterator & operator=(const iterator & it) { ptr_ = it.ptr_; return *this; }
00070 
00071       // constructor for static_array
00072       iterator(pointer ptr) : ptr_(ptr) {}
00073 
00074       // equal and inequal compareable
00075       bool operator==(const iterator& i) const { return ptr_ == i.ptr_; }
00076       bool operator!=(const iterator& i) const { return ptr_ != i.ptr_; }
00077 
00078       bool operator==(const const_iterator & it) const;
00079       bool operator!=(const const_iterator & it) const;
00080 
00081       // dereferenceable
00082       reference operator*() const { return *ptr_; }
00083       pointer operator->() const { return ptr_; }
00084 
00085       // increment- and decrementable
00086       iterator & operator++() { ++ptr_; return *this; }
00087       iterator operator++(int) { iterator tmp = *this; ++*this; return tmp; }
00088 
00089       iterator & operator--() { --ptr_; return *this; }
00090       iterator operator--(int) { iterator tmp = *this; --*this; return tmp; }
00091 
00092       // add and subtractable; operator+ and operator- is below
00093       difference_type operator-(const iterator & it) const { return ptr_ - it.ptr_; }
00094       difference_type operator-(const const_iterator & it) const { return ptr_ - it.ptr_; }
00095 
00096       // less and greater compareable
00097       bool operator<(const iterator & it) const { return ptr_ < it.ptr; }
00098       bool operator<=(const iterator & it) const { return ptr_ <= it.ptr; }
00099 
00100       bool operator>(const iterator & it) const { return ptr_ > it.ptr; }
00101       bool operator>=(const iterator & it) const { return ptr_ >= it.ptr; }
00102 
00103       bool operator<(const const_iterator & it) const { return ptr_ < it.ptr; }
00104       bool operator<=(const const_iterator & it) const { return ptr_ <= it.ptr; }
00105 
00106       bool operator>(const const_iterator & it) const { return ptr_ > it.ptr; }
00107       bool operator>=(const const_iterator & it) const { return ptr_ >= it.ptr; }
00108 
00109       // compound assign add- and subtractable
00110       iterator & operator+=(long diff) { ptr_ += diff; return *this; }
00111       iterator & operator-=(long diff) { ptr_ -= diff; return *this; }
00112 
00113       iterator operator+(long diff) { iterator tmp(*this); tmp += diff; return tmp; }
00114       iterator operator-(long diff) { iterator tmp(*this); tmp -= diff; return tmp; }
00115 
00116       // offset dereferenceable
00117       reference operator[](std::size_t offset) { return *(ptr_+offset); }
00118       const_reference operator[](std::size_t offset) const { return *(ptr_+offset); }
00119 
00120     private:
00121       pointer ptr_;
00122     };
00123 
00124     class const_iterator
00125     {
00126       friend class iterator;
00127     public:
00128 
00129       typedef std::size_t difference_type;
00130       typedef typename static_array::value_type value_type;
00131       typedef typename static_array::const_pointer pointer;
00132       typedef typename static_array::const_reference reference;
00133       typedef std::random_access_iterator_tag iterator_category;
00134 
00135 
00136       // default-constructable
00137       const_iterator() : ptr_(0) {}
00138 
00139       // copy- and copy-constructable
00140       const_iterator(const const_iterator & it) : ptr_(it.ptr_) {}
00141       const_iterator(iterator it) : ptr_(it.ptr_) {}
00142       const_iterator & operator=(const iterator & it) { ptr_ = it.ptr_; return *this; }
00143       const_iterator & operator=(const const_iterator & it) { ptr_ = it.ptr_; return *this; }
00144 
00145       // constructor for static_array
00146       const_iterator(const_pointer ptr) : ptr_(ptr) {}
00147 
00148       // equal and inequal compareable
00149       bool operator==(const const_iterator& i) const { return ptr_ == i.ptr_; }
00150       bool operator!=(const const_iterator& i) const { return ptr_ != i.ptr_; }
00151 
00152       bool operator==(const iterator & i) const { return ptr_ == i.ptr_; }
00153       bool operator!=(const iterator & i) const { return ptr_ != i.ptr_; }
00154 
00155       // dereferenceable
00156       reference operator*() const { return *ptr_; }
00157       pointer operator->() const { return ptr_; }
00158 
00159 
00160       // increment- and decrementable
00161       const_iterator & operator++() { ++ptr_; return *this; }
00162       const_iterator operator++(int) { const_iterator tmp = *this; ++*this; return tmp; }
00163 
00164       const_iterator & operator--() { --ptr_; return *this; }
00165       const_iterator operator--(int) { const_iterator tmp = *this; --*this; return tmp; }
00166 
00167       // add and subtractable; operator+ and operator- is below
00168       difference_type operator-(const iterator & it) const { return ptr_ - it.ptr_; }
00169       difference_type operator-(const const_iterator & it) const { return ptr_ - it.ptr_; }
00170 
00171       // less and greater compareable
00172       bool operator<(const iterator & it) const { return ptr_ < it.ptr; }
00173       bool operator<=(const iterator & it) const { return ptr_ <= it.ptr; }
00174 
00175       bool operator>(const iterator & it) const { return ptr_ > it.ptr; }
00176       bool operator>=(const iterator & it) const { return ptr_ >= it.ptr; }
00177 
00178       bool operator<(const const_iterator & it) const { return ptr_ < it.ptr; }
00179       bool operator<=(const const_iterator & it) const { return ptr_ <= it.ptr; }
00180 
00181       bool operator>(const const_iterator & it) const { return ptr_ > it.ptr; }
00182       bool operator>=(const const_iterator & it) const { return ptr_ >= it.ptr; }
00183 
00184       // compound assign add- and subtractable
00185       const_iterator & operator+=(long diff) { ptr_ += diff; return *this; }
00186       const_iterator & operator-=(long diff) { ptr_ -= diff; return *this; }
00187 
00188       const_iterator operator+(long diff) { const_iterator tmp(*this); tmp += diff; return tmp; }
00189       const_iterator operator-(long diff) { const_iterator tmp(*this); tmp -= diff; return tmp; }
00190 
00191       // offset dereferenceable
00192       reference operator[](std::size_t offset) { return *(ptr_+offset); }
00193 
00194     private:
00195       pointer ptr_;
00196     };
00197 
00198     // iterator support
00199     iterator        begin()       { return iterator(elements_); }
00200     const_iterator  begin() const { return const_iterator(elements_); }
00201     const_iterator cbegin() const { return const_iterator(elements_); }
00202 
00203     iterator        end()       { return iterator(elements_+N); }
00204     const_iterator  end() const { return const_iterator(elements_+N); }
00205     const_iterator cend() const { return const_iterator(elements_+N); }
00206 
00207     // reverse iterator support
00208     typedef std::reverse_iterator<iterator> reverse_iterator;
00209     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
00210 
00211     reverse_iterator rbegin() { return reverse_iterator(end()); }
00212     const_reverse_iterator rbegin() const {
00213       return const_reverse_iterator(end());
00214     }
00215     const_reverse_iterator crbegin() const {
00216       return const_reverse_iterator(end());
00217     }
00218 
00219     reverse_iterator rend() { return reverse_iterator(begin()); }
00220     const_reverse_iterator rend() const {
00221       return const_reverse_iterator(begin());
00222     }
00223     const_reverse_iterator crend() const {
00224       return const_reverse_iterator(begin());
00225     }
00226 
00227     // operator[]
00228     reference operator[](size_type i)
00229     {
00230       assert( i < N && "out of range" );
00231       return elements_[i];
00232     }
00233 
00234     const_reference operator[](size_type i) const
00235     {
00236       assert( i < N && "out of range" );
00237       return elements_[i];
00238     }
00239 
00240     // at() with range check
00241     reference at(size_type i) { assert( i < N && "out of range" );  return elements_[i]; }
00242     const_reference at(size_type i) const { assert( i < N && "out of range" );  return elements_[i]; }
00243 
00244     // front() and back()
00245     reference front()
00246     {
00247       return elements_[0];
00248     }
00249 
00250     const_reference front() const
00251     {
00252       return elements_[0];
00253     }
00254 
00255     reference back()
00256     {
00257       return elements_[N-1];
00258     }
00259 
00260     const_reference back() const
00261     {
00262       return elements_[N-1];
00263     }
00264 
00265     // size is constant
00266     static size_type size() { return N; }
00267     static void resize(size_type s) { assert( s <= N ); (void)s; }
00268 
00269     static bool empty() { return false; }
00270     static size_type max_size() { return N; }
00271     static const int static_size = N;
00272 
00273     // swap (note: linear complexity)
00274     void swap (static_array<T,N>& y) {
00275       for (size_type i = 0; i < N; ++i)
00276         std::swap(elements_[i],y.elements_[i]);
00277     }
00278 
00279     // direct access to data (read-only)
00280     const T* data() const { return elements_; }
00281     T* data() { return elements_; }
00282 
00283     // use static_array as C array (direct read/write access to data)
00284     T* c_array() { return elements_; }
00285 
00286     // assignment with type conversion
00287     template <typename T2>
00288     static_array<T,N>& operator= (const static_array<T2,N>& rhs) {
00289       std::copy(rhs.begin(),rhs.end(), begin());
00290       return *this;
00291     }
00292 
00293     // assign one value to all elements
00294     void assign (const T& value) { fill ( value ); }    // A synonym for fill
00295     void fill   (const T& value)
00296     {
00297       std::fill_n(begin(),size(),value);
00298     }
00299 
00300   };
00301 
00302   // comparisons
00303   template<class T, std::size_t N>
00304   bool operator== (const static_array<T,N>& x, const static_array<T,N>& y) {
00305     return std::equal(x.begin(), x.end(), y.begin());
00306   }
00307   template<class T, std::size_t N>
00308   bool operator< (const static_array<T,N>& x, const static_array<T,N>& y) {
00309     return std::lexicographical_compare(x.begin(),x.end(),y.begin(),y.end());
00310   }
00311   template<class T, std::size_t N>
00312   bool operator!= (const static_array<T,N>& x, const static_array<T,N>& y) {
00313     return !(x==y);
00314   }
00315   template<class T, std::size_t N>
00316   bool operator> (const static_array<T,N>& x, const static_array<T,N>& y) {
00317     return y<x;
00318   }
00319   template<class T, std::size_t N>
00320   bool operator<= (const static_array<T,N>& x, const static_array<T,N>& y) {
00321     return !(y<x);
00322   }
00323   template<class T, std::size_t N>
00324   bool operator>= (const static_array<T,N>& x, const static_array<T,N>& y) {
00325     return !(x<y);
00326   }
00327 
00328   // global swap()
00330   template<class T, std::size_t N>
00331   inline void swap (static_array<T,N>& x, static_array<T,N>& y) {
00332     x.swap(y);
00333   }
00334 
00335 }
00336 
00337 #endif