]>
Commit | Line | Data |
---|---|---|
92f5a8d4 TL |
1 | // Copyright 2019 Hans Dembinski |
2 | // | |
3 | // Distributed under the Boost Software License, Version 1.0. | |
4 | // (See accompanying file LICENSE_1_0.txt | |
5 | // or copy at http://www.boost.org/LICENSE_1_0.txt) | |
6 | ||
7 | #ifndef BOOST_HISTOGRAM_DETAIL_SPAN_HPP | |
8 | #define BOOST_HISTOGRAM_DETAIL_SPAN_HPP | |
9 | ||
f67539c2 TL |
10 | #ifdef __has_include |
11 | #if __has_include(<version>) | |
12 | #include <version> | |
13 | #ifdef __cpp_lib_span | |
14 | #if __cpp_lib_span >= 201902 | |
15 | #define BOOST_HISTOGRAM_DETAIL_HAS_STD_SPAN | |
16 | #endif | |
17 | #endif | |
18 | #endif | |
19 | #endif | |
20 | ||
21 | #ifdef BOOST_HISTOGRAM_DETAIL_HAS_STD_SPAN | |
22 | ||
92f5a8d4 TL |
23 | #include <span> |
24 | ||
25 | namespace boost { | |
26 | namespace histogram { | |
27 | namespace detail { | |
28 | using std::span; | |
29 | } // namespace detail | |
30 | } // namespace histogram | |
31 | } // namespace boost | |
32 | ||
33 | #else // C++17 span not available, so we use our implementation | |
34 | ||
35 | // to be replaced by boost::span | |
36 | ||
37 | #include <array> | |
20effc67 TL |
38 | #include <boost/histogram/detail/nonmember_container_access.hpp> |
39 | #include <cassert> | |
92f5a8d4 TL |
40 | #include <initializer_list> |
41 | #include <iterator> | |
42 | #include <type_traits> | |
43 | ||
44 | namespace boost { | |
45 | namespace histogram { | |
46 | namespace detail { | |
47 | ||
48 | namespace dtl = ::boost::histogram::detail; | |
49 | ||
50 | static constexpr std::size_t dynamic_extent = ~static_cast<std::size_t>(0); | |
51 | ||
52 | template <class T, std::size_t N> | |
53 | class span_base { | |
54 | public: | |
55 | constexpr T* data() noexcept { return begin_; } | |
56 | constexpr const T* data() const noexcept { return begin_; } | |
57 | constexpr std::size_t size() const noexcept { return N; } | |
58 | ||
59 | protected: | |
20effc67 TL |
60 | constexpr span_base(T* b, std::size_t s) noexcept : begin_(b) { |
61 | (void)s; | |
62 | assert(N == s); | |
63 | } | |
92f5a8d4 | 64 | constexpr void set(T* b, std::size_t s) noexcept { |
20effc67 | 65 | (void)s; |
92f5a8d4 | 66 | begin_ = b; |
20effc67 | 67 | assert(N == s); |
92f5a8d4 TL |
68 | } |
69 | ||
70 | private: | |
71 | T* begin_; | |
72 | }; | |
73 | ||
74 | template <class T> | |
75 | class span_base<T, dynamic_extent> { | |
76 | public: | |
20effc67 TL |
77 | constexpr span_base() noexcept : begin_(nullptr), size_(0) {} |
78 | ||
92f5a8d4 TL |
79 | constexpr T* data() noexcept { return begin_; } |
80 | constexpr const T* data() const noexcept { return begin_; } | |
81 | constexpr std::size_t size() const noexcept { return size_; } | |
82 | ||
83 | protected: | |
84 | constexpr span_base(T* b, std::size_t s) noexcept : begin_(b), size_(s) {} | |
92f5a8d4 TL |
85 | constexpr void set(T* b, std::size_t s) noexcept { |
86 | begin_ = b; | |
87 | size_ = s; | |
88 | } | |
89 | ||
90 | private: | |
91 | T* begin_; | |
92 | std::size_t size_; | |
93 | }; | |
94 | ||
95 | template <class T, std::size_t Extent = dynamic_extent> | |
96 | class span : public span_base<T, Extent> { | |
97 | using base = span_base<T, Extent>; | |
98 | ||
99 | public: | |
100 | using element_type = T; | |
101 | using value_type = std::remove_cv_t<T>; | |
102 | using index_type = std::size_t; | |
103 | using difference_type = std::ptrdiff_t; | |
104 | using pointer = T*; | |
105 | using const_pointer = const T*; | |
106 | using reference = T&; | |
107 | using const_reference = const T&; | |
108 | using iterator = pointer; | |
109 | using const_iterator = const_pointer; | |
110 | using reverse_iterator = std::reverse_iterator<iterator>; | |
111 | using const_reverse_iterator = std::reverse_iterator<const_iterator>; | |
112 | ||
113 | static constexpr std::size_t extent = Extent; | |
114 | ||
20effc67 | 115 | using base::base; |
92f5a8d4 TL |
116 | |
117 | constexpr span(pointer first, pointer last) | |
118 | : span(first, static_cast<std::size_t>(last - first)) { | |
20effc67 TL |
119 | assert(extent == dynamic_extent || |
120 | static_cast<difference_type>(extent) == (last - first)); | |
92f5a8d4 TL |
121 | } |
122 | ||
123 | constexpr span(pointer ptr, index_type count) : base(ptr, count) {} | |
124 | ||
125 | template <std::size_t N> | |
126 | constexpr span(element_type (&arr)[N]) noexcept : span(dtl::data(arr), N) { | |
127 | static_assert(extent == dynamic_extent || extent == N, "static sizes do not match"); | |
128 | } | |
129 | ||
130 | template <std::size_t N, | |
131 | class = std::enable_if_t<(extent == dynamic_extent || extent == N)> > | |
132 | constexpr span(std::array<value_type, N>& arr) noexcept : span(dtl::data(arr), N) {} | |
133 | ||
134 | template <std::size_t N, | |
135 | class = std::enable_if_t<(extent == dynamic_extent || extent == N)> > | |
136 | constexpr span(const std::array<value_type, N>& arr) noexcept | |
137 | : span(dtl::data(arr), N) {} | |
138 | ||
139 | template <class Container, class = std::enable_if_t<std::is_convertible< | |
20effc67 TL |
140 | decltype(dtl::size(std::declval<const Container&>()), |
141 | dtl::data(std::declval<const Container&>())), | |
92f5a8d4 TL |
142 | pointer>::value> > |
143 | constexpr span(const Container& cont) : span(dtl::data(cont), dtl::size(cont)) {} | |
144 | ||
145 | template <class Container, class = std::enable_if_t<std::is_convertible< | |
20effc67 TL |
146 | decltype(dtl::size(std::declval<Container&>()), |
147 | dtl::data(std::declval<Container&>())), | |
92f5a8d4 TL |
148 | pointer>::value> > |
149 | constexpr span(Container& cont) : span(dtl::data(cont), dtl::size(cont)) {} | |
150 | ||
151 | template <class U, std::size_t N, | |
152 | class = std::enable_if_t<((extent == dynamic_extent || extent == N) && | |
153 | std::is_convertible<U, element_type>::value)> > | |
154 | constexpr span(const span<U, N>& s) noexcept : span(s.data(), s.size()) {} | |
155 | ||
156 | template <class U, std::size_t N, | |
157 | class = std::enable_if_t<((extent == dynamic_extent || extent == N) && | |
158 | std::is_convertible<U, element_type>::value)> > | |
159 | constexpr span(span<U, N>& s) noexcept : span(s.data(), s.size()) {} | |
160 | ||
161 | constexpr span(const span& other) noexcept = default; | |
162 | ||
163 | constexpr iterator begin() { return base::data(); } | |
164 | constexpr const_iterator begin() const { return base::data(); } | |
165 | constexpr const_iterator cbegin() const { return base::data(); } | |
166 | ||
167 | constexpr iterator end() { return base::data() + base::size(); } | |
168 | constexpr const_iterator end() const { return base::data() + base::size(); } | |
169 | constexpr const_iterator cend() const { return base::data() + base::size(); } | |
170 | ||
171 | reverse_iterator rbegin() { return reverse_iterator(end()); } | |
172 | const_reverse_iterator rbegin() const { return reverse_iterator(end()); } | |
173 | const_reverse_iterator crbegin() { return reverse_iterator(end()); } | |
174 | ||
175 | reverse_iterator rend() { return reverse_iterator(begin()); } | |
176 | const_reverse_iterator rend() const { return reverse_iterator(begin()); } | |
177 | const_reverse_iterator crend() { return reverse_iterator(begin()); } | |
178 | ||
20effc67 TL |
179 | constexpr reference front() { return *base::data(); } |
180 | constexpr reference back() { return *(base::data() + base::size() - 1); } | |
92f5a8d4 TL |
181 | |
182 | constexpr reference operator[](index_type idx) const { return base::data()[idx]; } | |
183 | ||
184 | constexpr std::size_t size_bytes() const noexcept { | |
185 | return base::size() * sizeof(element_type); | |
186 | } | |
187 | ||
188 | constexpr bool empty() const noexcept { return base::size() == 0; } | |
189 | ||
190 | template <std::size_t Count> | |
191 | constexpr span<element_type, Count> first() const { | |
20effc67 | 192 | assert(Count <= base::size()); |
92f5a8d4 TL |
193 | return span<element_type, Count>(base::data(), Count); |
194 | } | |
195 | ||
196 | constexpr span<element_type, dynamic_extent> first(std::size_t count) const { | |
20effc67 | 197 | assert(count <= base::size()); |
92f5a8d4 TL |
198 | return span<element_type, dynamic_extent>(base::data(), count); |
199 | } | |
200 | ||
201 | template <std::size_t Count> | |
202 | constexpr span<element_type, Count> last() const { | |
20effc67 | 203 | assert(Count <= base::size()); |
92f5a8d4 TL |
204 | return span<element_type, Count>(base::data() + base::size() - Count, Count); |
205 | } | |
206 | ||
207 | constexpr span<element_type, dynamic_extent> last(std::size_t count) const { | |
20effc67 | 208 | assert(count <= base::size()); |
92f5a8d4 TL |
209 | return span<element_type, dynamic_extent>(base::data() + base::size() - count, count); |
210 | } | |
211 | ||
212 | template <std::size_t Offset, std::size_t Count = dynamic_extent> | |
213 | constexpr span<element_type, | |
214 | (Count != dynamic_extent | |
215 | ? Count | |
216 | : (extent != dynamic_extent ? extent - Offset : dynamic_extent))> | |
217 | subspan() const { | |
20effc67 | 218 | assert(Offset <= base::size()); |
92f5a8d4 TL |
219 | constexpr std::size_t E = |
220 | (Count != dynamic_extent | |
221 | ? Count | |
222 | : (extent != dynamic_extent ? extent - Offset : dynamic_extent)); | |
20effc67 | 223 | assert(E == dynamic_extent || E <= base::size()); |
92f5a8d4 TL |
224 | return span<element_type, E>(base::data() + Offset, |
225 | Count == dynamic_extent ? base::size() - Offset : Count); | |
226 | } | |
227 | ||
228 | constexpr span<element_type, dynamic_extent> subspan( | |
229 | std::size_t offset, std::size_t count = dynamic_extent) const { | |
20effc67 | 230 | assert(offset <= base::size()); |
92f5a8d4 | 231 | const std::size_t s = count == dynamic_extent ? base::size() - offset : count; |
20effc67 | 232 | assert(s <= base::size()); |
92f5a8d4 TL |
233 | return span<element_type, dynamic_extent>(base::data() + offset, s); |
234 | } | |
235 | }; | |
236 | ||
237 | } // namespace detail | |
238 | } // namespace histogram | |
239 | } // namespace boost | |
240 | ||
241 | #endif | |
242 | ||
20effc67 | 243 | #include <boost/histogram/detail/nonmember_container_access.hpp> |
92f5a8d4 TL |
244 | #include <utility> |
245 | ||
246 | namespace boost { | |
247 | namespace histogram { | |
248 | namespace detail { | |
249 | ||
250 | namespace dtl = ::boost::histogram::detail; | |
251 | ||
252 | template <class T> | |
253 | auto make_span(T* begin, T* end) { | |
254 | return dtl::span<T>{begin, end}; | |
255 | } | |
256 | ||
257 | template <class T> | |
258 | auto make_span(T* begin, std::size_t size) { | |
259 | return dtl::span<T>{begin, size}; | |
260 | } | |
261 | ||
262 | template <class Container, class = decltype(dtl::size(std::declval<Container>()), | |
263 | dtl::data(std::declval<Container>()))> | |
264 | auto make_span(const Container& cont) { | |
265 | return make_span(dtl::data(cont), dtl::size(cont)); | |
266 | } | |
267 | ||
268 | template <class T, std::size_t N> | |
269 | auto make_span(T (&arr)[N]) { | |
270 | return dtl::span<T, N>(arr, N); | |
271 | } | |
272 | ||
273 | } // namespace detail | |
274 | } // namespace histogram | |
275 | } // namespace boost | |
276 | ||
277 | #endif |