fix spurious warning about shifting more than size of type
[kazan.git] / src / util / constexpr_array.h
1 /*
2 * Copyright 2017 Jacob Lifshay
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in all
12 * copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 * SOFTWARE.
21 *
22 */
23
24 #ifndef UTIL_CONSTEXPR_ARRAY_H_
25 #define UTIL_CONSTEXPR_ARRAY_H_
26
27 #include "is_swappable.h"
28 #include <type_traits>
29 #include <utility>
30 #include <iterator>
31 #include <stdexcept>
32
33 namespace vulkan_cpu
34 {
35 namespace util
36 {
37 namespace detail
38 {
39 template <typename T, std::size_t N>
40 struct Constexpr_array_helper
41 {
42 typedef T values_type[N];
43 static constexpr T *get_values_pointer(values_type &values) noexcept
44 {
45 return values;
46 }
47 static constexpr const T *get_values_pointer(const values_type &values) noexcept
48 {
49 return values;
50 }
51 };
52
53 template <typename T>
54 struct Constexpr_array_helper<T, 0>
55 {
56 struct values_type
57 {
58 };
59 static constexpr T *get_values_pointer(values_type &values) noexcept
60 {
61 return nullptr;
62 }
63 static constexpr const T *get_values_pointer(const values_type &values) noexcept
64 {
65 return nullptr;
66 }
67 };
68 }
69
70 template <typename T, std::size_t N>
71 struct Constexpr_array
72 {
73 private:
74 typedef detail::Constexpr_array_helper<T, N> Helper;
75 typedef typename Helper::values_type values_type;
76 constexpr T *get_values_pointer() noexcept
77 {
78 return Helper::get_values_pointer(values);
79 }
80 constexpr const T *get_values_pointer() const noexcept
81 {
82 return Helper::get_values_pointer(values);
83 }
84
85 public:
86 values_type values;
87 typedef T value_type;
88 typedef std::size_t size_type;
89 typedef std::ptrdiff_t difference_type;
90 typedef T &reference;
91 typedef const T &const_reference;
92 typedef T *pointer;
93 typedef const T *const_pointer;
94 typedef T *iterator;
95 typedef const T *const_iterator;
96 typedef std::reverse_iterator<iterator> reverse_iterator;
97 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
98 constexpr T &at(std::size_t index)
99 {
100 if(index >= N)
101 throw std::out_of_range("Constexpr_array::at");
102 return get_values_pointer()[index];
103 }
104 constexpr const T &at(std::size_t index) const
105 {
106 if(index >= N)
107 throw std::out_of_range("Constexpr_array::at");
108 return get_values_pointer()[index];
109 }
110 constexpr T &operator[](std::size_t index) noexcept
111 {
112 return get_values_pointer()[index];
113 }
114 constexpr const T &operator[](std::size_t index) const noexcept
115 {
116 return get_values_pointer()[index];
117 }
118 constexpr T &front() noexcept
119 {
120 return get_values_pointer()[0];
121 }
122 constexpr const T &front() const noexcept
123 {
124 return get_values_pointer()[0];
125 }
126 constexpr T &back() noexcept
127 {
128 return get_values_pointer()[N - 1];
129 }
130 constexpr const T &back() const noexcept
131 {
132 return get_values_pointer()[N - 1];
133 }
134 constexpr T *data() noexcept
135 {
136 return get_values_pointer();
137 }
138 constexpr const T *data() const noexcept
139 {
140 return get_values_pointer();
141 }
142 constexpr iterator begin() noexcept
143 {
144 return get_values_pointer();
145 }
146 constexpr const_iterator begin() const noexcept
147 {
148 return get_values_pointer();
149 }
150 constexpr const_iterator cbegin() const noexcept
151 {
152 return get_values_pointer();
153 }
154 constexpr iterator end() noexcept
155 {
156 return get_values_pointer() + N;
157 }
158 constexpr const_iterator end() const noexcept
159 {
160 return get_values_pointer() + N;
161 }
162 constexpr const_iterator cend() const noexcept
163 {
164 return get_values_pointer() + N;
165 }
166 constexpr reverse_iterator rbegin() noexcept
167 {
168 return reverse_iterator(end());
169 }
170 constexpr const_reverse_iterator rbegin() const noexcept
171 {
172 return const_reverse_iterator(end());
173 }
174 constexpr const_reverse_iterator crbegin() const noexcept
175 {
176 return const_reverse_iterator(end());
177 }
178 constexpr reverse_iterator rend() noexcept
179 {
180 return reverse_iterator(begin());
181 }
182 constexpr const_reverse_iterator rend() const noexcept
183 {
184 return const_reverse_iterator(begin());
185 }
186 constexpr const_reverse_iterator crend() const noexcept
187 {
188 return const_reverse_iterator(begin());
189 }
190 constexpr bool empty() const noexcept
191 {
192 return size() == 0;
193 }
194 constexpr std::size_t size() const noexcept
195 {
196 return N;
197 }
198 constexpr std::size_t max_size() const noexcept
199 {
200 return N;
201 }
202 constexpr void fill(const T &value) noexcept(std::is_nothrow_copy_assignable<T>::value)
203 {
204 for(auto &i : *this)
205 i = value;
206 }
207 constexpr void swap(Constexpr_array &other) noexcept(is_nothrow_swappable_v<T>)
208 {
209 using std::swap;
210 for(std::size_t index = 0; index < size(); index++)
211 swap(get_values_pointer()[index], other.get_values_pointer()[index]);
212 }
213 };
214
215 template <typename T, std::size_t N>
216 constexpr void swap(Constexpr_array<T, N> &a,
217 Constexpr_array<T, N> &b) noexcept(is_nothrow_swappable_v<T>)
218 {
219 a.swap(b);
220 }
221
222 template <std::size_t I, typename T, std::size_t N>
223 constexpr T &get(Constexpr_array<T, N> &v) noexcept
224 {
225 static_assert(I < N, "");
226 return v[I];
227 }
228
229 template <std::size_t I, typename T, std::size_t N>
230 constexpr const T &get(const Constexpr_array<T, N> &v) noexcept
231 {
232 static_assert(I < N, "");
233 return v[I];
234 }
235
236 template <std::size_t I, typename T, std::size_t N>
237 constexpr const T &&get(const Constexpr_array<T, N> &&v) noexcept
238 {
239 static_assert(I < N, "");
240 return std::move(v[I]);
241 }
242
243 template <std::size_t I, typename T, std::size_t N>
244 constexpr T &&get(Constexpr_array<T, N> &&v) noexcept
245 {
246 static_assert(I < N, "");
247 return std::move(v[I]);
248 }
249 }
250 }
251
252 #endif /* UTIL_CONSTEXPR_ARRAY_H_ */