CMS 3D CMS Logo

StdArray.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_interface_StdArray_h
2 #define DataFormats_Common_interface_StdArray_h
3 
4 #include <array>
5 #include <cstddef>
6 #include <iostream>
7 #include <iterator>
8 
10 
11 namespace edm {
12 
13  // Due to a ROOT limitation an std::array cannot be serialised to a ROOT file.
14  // See https://github.com/root-project/root/issues/12007 for a discussion on the issue.
15  //
16  // This class reimplements the full std::array<T,N> interface, using a regular
17  // Reflex dictionary for the ROOT serialisation.
18  // To be more GPU-friendly, all methods are constexpr, and out-of-bound data access
19  // aborts instead of throwing an exception.
20  //
21  // Note: dictonaries for edm::StdArray<T,N> where T is a standard C/C++ type
22  // should be declared in DataFormats/Common/src/classed_def.xml.
23 
24  namespace detail {
25  template <typename T, std::size_t N>
26  class StdArrayTrait {
27  public:
28  using array_type = T[N];
29  };
30 
31  template <typename T>
32  class StdArrayTrait<T, 0> {
33  public:
34  struct array_type {};
35  };
36  } // namespace detail
37 
38  template <typename T, std::size_t N>
39  class StdArray {
40  public:
41  // Member types
42 
43  using value_type = T;
44  using size_type = std::size_t;
45  using difference_type = std::ptrdiff_t;
47  using const_reference = value_type const&;
48  using pointer = value_type*;
49  using const_pointer = const value_type*;
50  using iterator = pointer;
52  using reverse_iterator = std::reverse_iterator<iterator>;
53  using const_reverse_iterator = std::reverse_iterator<const_iterator>;
54 
55  // Interoperability with std::array
56 
57  // copy assignment from an std::array
58  constexpr StdArray& operator=(std::array<T, N> const& init) {
59  for (size_type i = 0; i < N; ++i) {
60  data_[i] = init[i];
61  }
62  return *this;
63  }
64 
65  // move assignment from an std::array
66  constexpr StdArray& operator=(std::array<T, N>&& init) {
67  for (size_type i = 0; i < N; ++i) {
68  data_[i] = std::move(init[i]);
69  }
70  return *this;
71  }
72 
73  // cast operator to an std::array
74  constexpr operator std::array<T, N>() const {
75  std::array<T, N> copy;
76  for (size_type i = 0; i < N; ++i) {
77  copy[i] = data_[i];
78  }
79  return copy;
80  }
81 
82  // Element access
83 
84  // Returns a reference to the element at specified location pos, with bounds checking.
85  // If pos is not within the range of the container, the program aborts.
86  constexpr reference at(size_type pos) {
87  if (pos >= N)
88  abort();
89  return data_[pos];
90  }
91  constexpr const_reference at(size_type pos) const {
92  if (pos >= N)
93  abort();
94  return data_[pos];
95  }
96 
97  // Returns a reference to the element at specified location pos. No bounds checking is performed.
98  constexpr reference operator[](size_type pos) { return data_[pos]; }
99  constexpr const_reference operator[](size_type pos) const { return data_[pos]; }
100 
101  // Returns a reference to the first element in the container.
102  // Calling front on an empty container causes the program to abort.
103  constexpr reference front() {
104  if constexpr (N == 0)
105  abort();
106  return data_[0];
107  }
108  constexpr const_reference front() const {
109  if constexpr (N == 0)
110  abort();
111  return data_[0];
112  }
113 
114  // Returns a reference to the last element in the container.
115  // Calling back on an empty container causes the program to abort.
116  constexpr reference back() {
117  if constexpr (N == 0)
118  abort();
119  return data_[N - 1];
120  }
121  constexpr const_reference back() const {
122  if constexpr (N == 0)
123  abort();
124  return data_[N - 1];
125  }
126 
127  // Returns pointer to the underlying array serving as element storage.
128  // The pointer is such that range [data(), data() + size()) is always a valid range,
129  // even if the container is empty (data() is not dereferenceable in that case).
130  constexpr pointer data() noexcept {
131  if constexpr (N != 0)
132  return data_;
133  else
134  return nullptr;
135  }
136  constexpr const_pointer data() const noexcept {
137  if constexpr (N != 0)
138  return data_;
139  else
140  return nullptr;
141  }
142 
143  // Iterators
144 
145  // Returns an iterator to the first element of the array.
146  // If the array is empty, the returned iterator will be equal to end().
147  constexpr iterator begin() noexcept {
148  if constexpr (N != 0)
149  return data_;
150  else
151  return nullptr;
152  }
153  constexpr const_iterator begin() const noexcept {
154  if constexpr (N != 0)
155  return data_;
156  else
157  return nullptr;
158  }
159  constexpr const_iterator cbegin() const noexcept {
160  if constexpr (N != 0)
161  return data_;
162  else
163  return nullptr;
164  }
165 
166  // Returns an iterator to the element following the last element of the array.
167  // This element acts as a placeholder; attempting to access it results in undefined behavior.
168  constexpr iterator end() noexcept {
169  if constexpr (N != 0)
170  return data_ + N;
171  else
172  return nullptr;
173  }
174  constexpr const_iterator end() const noexcept {
175  if constexpr (N != 0)
176  return data_ + N;
177  else
178  return nullptr;
179  }
180  constexpr const_iterator cend() const noexcept {
181  if constexpr (N != 0)
182  return data_ + N;
183  else
184  return nullptr;
185  }
186 
187  // Returns a reverse iterator to the first element of the reversed array.
188  // It corresponds to the last element of the non-reversed array. If the array is empty, the returned iterator is equal to rend().
189  constexpr reverse_iterator rbegin() noexcept { return reverse_iterator(end()); }
190  constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); }
191  constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(end()); }
192 
193  // Returns a reverse iterator to the element following the last element of the reversed array.
194  // It corresponds to the element preceding the first element of the non-reversed array. This element acts as a placeholder, attempting to access it results in undefined behavior.
195  constexpr reverse_iterator rend() noexcept { return reverse_iterator(begin()); }
196  constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); }
197  constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(begin()); }
198 
199  // Capacity
200 
201  // Checks if the container has no elements, i.e. whether begin() == end().
202  constexpr bool empty() const noexcept { return N == 0; }
203 
204  // Returns the number of elements in the container, i.e. std::distance(begin(), end()).
205  constexpr size_type size() const noexcept { return N; }
206 
207  // Returns the maximum number of elements the container is able to hold due to system or library implementation limitations, i.e. std::distance(begin(), end()) for the largest container.
208  constexpr size_type max_size() const noexcept { return N; }
209 
210  // Operations
211 
212  // Assigns the value to all elements in the container.
213  constexpr void fill(const T& value) {
214  for (size_type i = 0; i < N; ++i)
215  data_[i] = N;
216  }
217 
218  // Exchanges the contents of the container with those of other. Does not cause iterators and references to associate with the other container.
219  constexpr void swap(StdArray& other) noexcept(std::is_nothrow_swappable_v<T>) {
220  if (&other == this)
221  return;
222  for (size_type i = 0; i < N; ++i)
223  std::swap(data_[i], other[i]);
224  }
225 
226  // Data members
227 
228  // Use a public data member to allow aggregate initialisation
230 
231  // ROOT dictionary support for templated classes
233  };
234 
235  // comparison operator; T and U must be inequality comparable
236  template <class T, class U, std::size_t N>
237  constexpr bool operator==(StdArray<T, N> const& lhs, StdArray<U, N> const& rhs) {
238  for (std::size_t i = 0; i < N; ++i) {
239  if (lhs[i] != rhs[i])
240  return false;
241  }
242  return true;
243  }
244 
245  // output stream operator
246  template <typename T, std::size_t N>
247  std::ostream& operator<<(std::ostream& out, edm::StdArray<T, N> const& array) {
248  out << "{";
249  if constexpr (N > 0) {
250  out << " " << array[0];
251  }
252  for (std::size_t i = 1; i < N; ++i)
253  out << ", " << array[i];
254  out << " }";
255  return out;
256  }
257 
258 } // namespace edm
259 
260 #endif // DataFormats_Common_interface_StdArray_h
const value_type * const_pointer
Definition: StdArray.h:49
constexpr bool operator==(ELseverityLevel const &e1, ELseverityLevel const &e2) noexcept
constexpr void fill(const T &value)
Definition: StdArray.h:213
constexpr iterator begin() noexcept
Definition: StdArray.h:147
constexpr StdArray & operator=(std::array< T, N > &&init)
Definition: StdArray.h:66
constexpr const_pointer data() const noexcept
Definition: StdArray.h:136
constexpr reference front()
Definition: StdArray.h:103
constexpr pointer data() noexcept
Definition: StdArray.h:130
std::size_t size_type
Definition: StdArray.h:44
constexpr const_reference at(size_type pos) const
Definition: StdArray.h:91
constexpr reference operator[](size_type pos)
Definition: StdArray.h:98
constexpr reference back()
Definition: StdArray.h:116
constexpr StdArray & operator=(std::array< T, N > const &init)
Definition: StdArray.h:58
#define CMS_CLASS_VERSION(_version_)
void swap(Association< C > &lhs, Association< C > &rhs)
Definition: Association.h:112
constexpr const_iterator cbegin() const noexcept
Definition: StdArray.h:159
constexpr const_reference operator[](size_type pos) const
Definition: StdArray.h:99
constexpr reverse_iterator rbegin() noexcept
Definition: StdArray.h:189
value_type & reference
Definition: StdArray.h:46
const_pointer const_iterator
Definition: StdArray.h:51
constexpr const_iterator cend() const noexcept
Definition: StdArray.h:180
constexpr iterator end() noexcept
Definition: StdArray.h:168
std::ptrdiff_t difference_type
Definition: StdArray.h:45
Definition: value.py:1
value_type * pointer
Definition: StdArray.h:48
Definition: init.py:1
constexpr const_reverse_iterator rend() const noexcept
Definition: StdArray.h:196
constexpr bool empty() const noexcept
Definition: StdArray.h:202
#define N
Definition: blowfish.cc:9
constexpr reverse_iterator rend() noexcept
Definition: StdArray.h:195
pointer iterator
Definition: StdArray.h:50
constexpr const_iterator end() const noexcept
Definition: StdArray.h:174
HLT enums.
value_type const & const_reference
Definition: StdArray.h:47
constexpr const_iterator begin() const noexcept
Definition: StdArray.h:153
constexpr void swap(StdArray &other) noexcept(std::is_nothrow_swappable_v< T >)
Definition: StdArray.h:219
constexpr const_reverse_iterator crbegin() const noexcept
Definition: StdArray.h:191
constexpr const_reverse_iterator rbegin() const noexcept
Definition: StdArray.h:190
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition: StdArray.h:53
detail::StdArrayTrait< T, N >::array_type data_
Definition: StdArray.h:229
constexpr reference at(size_type pos)
Definition: StdArray.h:86
long double T
constexpr size_type max_size() const noexcept
Definition: StdArray.h:208
std::reverse_iterator< iterator > reverse_iterator
Definition: StdArray.h:52
constexpr const_reference back() const
Definition: StdArray.h:121
constexpr size_type size() const noexcept
Definition: StdArray.h:205
def move(src, dest)
Definition: eostools.py:511
constexpr const_reference front() const
Definition: StdArray.h:108
constexpr const_reverse_iterator crend() const noexcept
Definition: StdArray.h:197