M/c++_api/inc/DM/Array.hpp
1 #pragma once
2 
3 #include "DM/config.hpp"
4 #include "DM/AutoLink.hpp" //enable autolink
5 
6 // std::ptrdiff_t and std::size_t
7 //#include <cstddef>
8 // std::reverse_iterator<Iterator>
9 //#include <iterator>
10 // std::out_of_range
11 #include <stdexcept>
12 
13 
14 DM_NAMESPACE_BEGIN
15 
16  /**
17  \class Array
18  \tparam T the element type
19  \tparam N the constant size, must be >= 1
20 
21  \brief a template class holding a C-array of constant size.
22 
23  \author wk
24  \date 03.02.2011
25 
26  Array is an aggregate, meaning that it may be initialized with a static initializer list:
27  opals::Array<double,3> arr = { 1., 2., 3. };
28  Array fulfills almost all the requirements of an STL reversible container.
29  The complete implementation is exposed, why opals users may instantiate Array<T,N> with arbitrary template arguments.
30  The class closely follows boost::array.
31  \internal
32  opals::Array extends boost::array. Like boost::array, opals::Array is an aggregate,
33  as it defines no constructors and no protected/private data members (and no base class, no virtual functions).
34  As a consequence, opals::Array may be initialized with an initializer list,
35  but no conversion constructor from boost::array can be provided.
36  For that purpose, first instantiate the opals::Array, then assign the boost::array:
37  opals::Array<double,2> arr;
38  arr = boost_array_double_2_instance;
39  As extensions to boost::array, assignment of a C-array is supported:
40  double da[] = { 1., 2. };
41  arr = da;
42  In contrast to opals::Vector and opals::List,
43  its data member is a plain-old-C-array,
44  why the whole implementation can be exposed to DLL users, together with
45  global template comparison operators - mind that the C-array
46  must not be protected/private in order to keep Array an aggregate.
47  As further extensions to the interface of boost::array,
48  opals::Array provides operator<<, operator>>,
49  and function toInternal(),
50  which returns a boost::array<U>, where U is the internal type
51  corresponding to T (see InternalType).
52  In contrast to boost::array, Array may not be instantiated for N==0.
53  */
54 
55  template<class T, std::size_t N>
56  class DM_API Array
57  {
58 
59  public:
60 
61  T elems[N]; // fixed-size C-array of elements of type T
62 
63  // type definitions
64  typedef T value_type;
65  typedef T* iterator;
66  typedef const T* const_iterator;
67  typedef T& reference;
68  typedef const T& const_reference;
69  typedef std::size_t size_type;
70  typedef std::ptrdiff_t difference_type;
71  typedef std::reverse_iterator<iterator> reverse_iterator;
72  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
73  enum { static_size = N };
74 
75 
76  /// \name assignment, swapping
77  //@{
78  /// assignment with type conversion
79  template <typename T2>
80  Array<T,N>& operator= (const Array<T2,N> &other)
81  {
82  ::std::copy(other.begin(),other.end(), begin());
83  return *this;
84  }
85  /// assign a C-array with type conversion
86  template <typename T2>
87  Array<T,N>& operator= ( const T2 (&other) [N] )
88  {
89  std::copy(other,&other[N], begin());
90  return *this;
91  }
92 
93  /// assign one value to all elements
94  void assign(const T &val)
95  { std::fill_n(begin(),size(),val); }
96 
97  /// swap (linear complexity)
98  void swap(Array<T,N> &other)
99  { std::swap_ranges(begin(),end(),other.begin()); }
100  //}@
101 
102  /// \name iterator traversal
103  /// forward/reverse, const/non-const
104  //@{
105  iterator begin() { return elems; }
106  const_iterator begin() const { return elems; }
107  iterator end() { return elems+N; }
108  const_iterator end() const { return elems+N; }
109 
110  reverse_iterator rbegin() { return reverse_iterator(end()); }
111  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
112  reverse_iterator rend() { return reverse_iterator(begin()); }
113  const_reverse_iterator rend() const { return const_reverse_iterator(begin()); }
114  //}@
115 
116  /// \name direct element access with range check
117  /// zero-based indexing
118  //@{
119  reference operator[](size_type i) { rangecheck(i); return elems[i]; }
120  const_reference operator[](size_type i) const { rangecheck(i); return elems[i]; }
121  reference at(size_type i) { rangecheck(i); return elems[i]; }
122  const_reference at(size_type i) const { rangecheck(i); return elems[i]; }
123  //}@
124 
125 
126  /// \name first/last element
127  //@{
128  reference front() { return elems[0]; }
129  const_reference front() const { return elems[0]; }
130  reference back() { return elems[N-1]; }
131  const_reference back() const { return elems[N-1]; }
132  //}@
133 
134  /// \name direct access to C-array
135  //@{
136  const T* data() const { return elems; }
137  T* data() { return elems; }
138  T* c_array() { return elems; }
139  //}@
140 
141  /// \name size
142  //@{
143  static size_type size() { return N; }
144  static bool empty() { return false; }
145  static size_type max_size() { return N; }
146  //}@
147 
148  private:
149  static void rangecheck (size_type i)
150  {
151  if (i >= size()) {
152  throw std::out_of_range("Array<>: index out of range");
153  }
154  }
155  };
156 
157  template<class T>
158  class Array<T,0>
159  {
160  template<class U> struct Must_not_instantiate_an_empty_opals_Array;
161  typedef typename Must_not_instantiate_an_empty_opals_Array<T>::Type CompilationError;
162  };
163 
164  /// \relatesalso Array
165  template<class T, std::size_t N>
166  bool operator== (const Array<T,N>& l, const Array<T,N>& r) {
167  return std::equal(l.begin(), l.end(), r.begin());
168  }
169 
170  /// \relatesalso Array
171  template<class T, std::size_t N>
172  bool operator< (const Array<T,N>& l, const Array<T,N>& r) {
173  return std::lexicographical_compare(l.begin(),l.end(),r.begin(),r.end());
174  }
175 
176  /// \relatesalso Array
177  template<class T, std::size_t N>
178  bool operator!= (const Array<T,N>& l, const Array<T,N>& r) {
179  return !(l==r);
180  }
181 
182  /// \relatesalso Array
183  template<class T, std::size_t N>
184  bool operator> (const Array<T,N>& l, const Array<T,N>& r) {
185  return r<l;
186  }
187 
188  /// \relatesalso Array
189  template<class T, std::size_t N>
190  bool operator<= (const Array<T,N>& l, const Array<T,N>& r) {
191  return !(r<l);
192  }
193 
194  /// \relatesalso Array
195  template<class T, std::size_t N>
196  bool operator>= (const Array<T,N>& l, const Array<T,N>& r) {
197  return !(l<r);
198  }
199 
200  /// \relatesalso Array
201  template<class T, std::size_t N>
202  void swap (Array<T,N>& l, Array<T,N>& r) {
203  l.swap(r);
204  }
205 
206 DM_NAMESPACE_END
207 
void swap(Array< T, N > &other)
swap (linear complexity)
Definition: M/c++_api/inc/DM/Array.hpp:98
a template class holding a C-array of constant size.
Definition: M/c++_api/inc/DM/Array.hpp:56
void assign(const T &val)
assign one value to all elements
Definition: M/c++_api/inc/DM/Array.hpp:94