The Battle for Wesnoth  1.19.10+dev
span.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2025 - 2025
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 // We need to include *something* so __cpp_lib_span is defined properly here
18 #if __has_include(<version>)
19 #include <version>
20 #endif
21 
22 #include <boost/version.hpp>
23 
24 // C++20 compatible
25 #ifdef __cpp_lib_span
26 
27 #include <span>
28 namespace utils { using std::span; }
29 
30 // Boost 1.78 or later
31 #elif BOOST_VERSION >= 107800
32 
33 #include <boost/core/span.hpp>
34 namespace utils { using boost::span; }
35 
36 // Full manual fallback, copied from Boost with some tweaks
37 #else
38 
39 /*
40 Copyright 2019-2023 Glen Joseph Fernandes
41 (glenjofe@gmail.com)
42 
43 Distributed under the Boost Software License, Version 1.0.
44 (http://www.boost.org/LICENSE_1_0.txt)
45 */
46 
47 #include <array>
48 #include <cstddef>
49 #include <initializer_list>
50 #include <iterator>
51 #include <type_traits>
52 
53 namespace boost {
54 
55 template<class C>
56 inline constexpr auto
57 data(C& c) noexcept(noexcept(c.data())) -> decltype(c.data())
58 {
59  return c.data();
60 }
61 
62 template<class C>
63 inline constexpr auto
64 data(const C& c) noexcept(noexcept(c.data())) -> decltype(c.data())
65 {
66  return c.data();
67 }
68 
69 template<class T, std::size_t N>
70 inline constexpr T*
71 data(T(&a)[N]) noexcept
72 {
73  return a;
74 }
75 
76 template<class T>
77 inline constexpr const T*
78 data(std::initializer_list<T> l) noexcept
79 {
80  return l.begin();
81 }
82 
83 constexpr std::size_t dynamic_extent = static_cast<std::size_t>(-1);
84 
85 template<class T, std::size_t E = dynamic_extent>
86 class span;
87 
88 namespace detail {
89 
90 template<class U, class T>
92  static constexpr bool value = std::is_convertible<U(*)[], T(*)[]>::value;
93 };
94 
95 template<std::size_t E, std::size_t N>
96 struct span_capacity {
97  static constexpr bool value = E == boost::dynamic_extent || E == N;
98 };
99 
100 template<class T, std::size_t E, class U, std::size_t N>
102  static constexpr bool value = span_capacity<E, N>::value &&
104 };
105 
106 template<class T>
107 using span_uncvref = typename std::remove_cv<typename
109 
110 template<class>
111 struct span_is_span {
112  static constexpr bool value = false;
113 };
114 
115 template<class T, std::size_t E>
116 struct span_is_span<boost::span<T, E> > {
117  static constexpr bool value = true;
118 };
119 
120 template<class T>
122  static constexpr bool value = false;
123 };
124 
125 template<class T, std::size_t N>
126 struct span_is_array<std::array<T, N> > {
127  static constexpr bool value = true;
128 };
129 
130 template<class T>
131 using span_ptr = decltype(boost::data(std::declval<T&>()));
132 
133 template<class, class = void>
134 struct span_data { };
135 
136 template<class T>
137 struct span_data<T,
138  typename std::enable_if<std::is_pointer<span_ptr<T> >::value>::type> {
139  typedef typename std::remove_pointer<span_ptr<T> >::type type;
140 };
141 
142 template<class, class, class = void>
144  static constexpr bool value = false;
145 };
146 
147 template<class R, class T>
148 struct span_has_data<R, T, typename std::enable_if<span_convertible<typename
149  span_data<R>::type, T>::value>::type> {
150  static constexpr bool value = true;
151 };
152 
153 template<class, class = void>
155  static constexpr bool value = false;
156 };
157 
158 template<class R>
159 struct span_has_size<R, typename
160  std::enable_if<std::is_convertible<decltype(std::declval<R&>().size()),
161  std::size_t>::value>::type> {
162  static constexpr bool value = true;
163 };
164 
165 template<class R, class T>
167  static constexpr bool value = (std::is_const<T>::value ||
168  std::is_lvalue_reference<R>::value) &&
171  !std::is_array<span_uncvref<R> >::value &&
174 };
175 
176 template<std::size_t E, std::size_t N>
178  static constexpr bool value = E == boost::dynamic_extent ||
180 };
181 
182 template<class T, std::size_t E, class U, std::size_t N>
184  static constexpr bool value = (N == boost::dynamic_extent ||
186 };
187 
188 template<std::size_t E, std::size_t O>
189 struct span_sub {
190  static constexpr std::size_t value = E == boost::dynamic_extent ?
191  boost::dynamic_extent : E - O;
192 };
193 
194 template<class T, std::size_t E>
195 struct span_store {
196  constexpr span_store(T* p_, std::size_t) noexcept
197  : p(p_) { }
198  static constexpr std::size_t n = E;
199  T* p;
200 };
201 
202 template<class T>
204  constexpr span_store(T* p_, std::size_t n_) noexcept
205  : p(p_)
206  , n(n_) { }
207  T* p;
208  std::size_t n;
209 };
210 
211 template<class T, std::size_t E>
212 struct span_bytes {
213  static constexpr std::size_t value = sizeof(T) * E;
214 };
215 
216 template<class T>
218  static constexpr std::size_t value = boost::dynamic_extent;
219 };
220 
221 } /* detail */
222 
223 template<class T, std::size_t E>
224 class span {
225 public:
226  typedef T element_type;
228  typedef std::size_t size_type;
229  typedef std::ptrdiff_t difference_type;
230  typedef T* pointer;
231  typedef const T* const_pointer;
232  typedef T& reference;
233  typedef const T& const_reference;
234  typedef T* iterator;
235  typedef const T* const_iterator;
236  typedef std::reverse_iterator<T*> reverse_iterator;
237  typedef std::reverse_iterator<const T*> const_reverse_iterator;
238 
239  static constexpr std::size_t extent = E;
240 
241  template<std::size_t N = E,
243  constexpr span() noexcept
244  : s_(0, 0) { }
245 
246  template<class I,
247  typename std::enable_if<E == dynamic_extent &&
249  constexpr span(I* f, size_type c)
250  : s_(f, c) { }
251 
252  template<class I,
253  typename std::enable_if<E != dynamic_extent &&
255  explicit constexpr span(I* f, size_type c)
256  : s_(f, c) { }
257 
258  template<class I, class L,
259  typename std::enable_if<E == dynamic_extent &&
261  constexpr span(I* f, L* l)
262  : s_(f, l - f) { }
263 
264  template<class I, class L,
265  typename std::enable_if<E != dynamic_extent &&
267  explicit constexpr span(I* f, L* l)
268  : s_(f, l - f) { }
269 
270  template<std::size_t N,
271  typename std::enable_if<detail::span_capacity<E, N>::value,
272  int>::type = 0>
273  constexpr span(typename std::enable_if<true, T>::type (&a)[N]) noexcept
274  : s_(a, N) { }
275 
276  template<class U, std::size_t N,
277  typename std::enable_if<detail::span_compatible<T, E, U, N>::value,
278  int>::type = 0>
279  constexpr span(std::array<U, N>& a) noexcept
280  : s_(a.data(), N) { }
281 
282  template<class U, std::size_t N,
283  typename std::enable_if<detail::span_compatible<T, E, const U,
284  N>::value, int>::type = 0>
285  constexpr span(const std::array<U, N>& a) noexcept
286  : s_(a.data(), N) { }
287 
288  template<class R,
289  typename std::enable_if<E == dynamic_extent &&
291  constexpr span(R&& r) noexcept(noexcept(boost::data(r)) &&
292  noexcept(r.size()))
293  : s_(boost::data(r), r.size()) { }
294 
295  template<class R,
296  typename std::enable_if<E != dynamic_extent &&
298  explicit constexpr span(R&& r) noexcept(noexcept(boost::data(r)) &&
299  noexcept(r.size()))
300  : s_(boost::data(r), r.size()) { }
301 
302  template<class U, std::size_t N,
303  typename std::enable_if<detail::span_implicit<E, N>::value &&
305  constexpr span(const span<U, N>& s) noexcept
306  : s_(s.data(), s.size()) { }
307 
308  template<class U, std::size_t N,
309  typename std::enable_if<!detail::span_implicit<E, N>::value &&
311  explicit constexpr span(const span<U, N>& s) noexcept
312  : s_(s.data(), s.size()) { }
313 
314  template<std::size_t C>
315  constexpr span<T, C> first() const {
316  static_assert(C <= E, "Count <= Extent");
317  return span<T, C>(s_.p, C);
318  }
319 
320  template<std::size_t C>
321  constexpr span<T, C> last() const {
322  static_assert(C <= E, "Count <= Extent");
323  return span<T, C>(s_.p + (s_.n - C), C);
324  }
325 
326  template<std::size_t O, std::size_t C = dynamic_extent>
327  constexpr typename std::enable_if<C == dynamic_extent,
329  static_assert(O <= E, "Offset <= Extent");
330  return span<T, detail::span_sub<E, O>::value>(s_.p + O, s_.n - O);
331  }
332 
333  template<std::size_t O, std::size_t C = dynamic_extent>
334  constexpr typename std::enable_if<C != dynamic_extent,
336  static_assert(O <= E && C <= E - O,
337  "Offset <= Extent && Count <= Extent - Offset");
338  return span<T, C>(s_.p + O, C);
339  }
340 
342  return span<T, dynamic_extent>(s_.p, c);
343  }
344 
346  return span<T, dynamic_extent>(s_.p + (s_.n - c), c);
347  }
348 
350  size_type c = dynamic_extent) const {
351  return span<T, dynamic_extent>(s_.p + o,
352  c == dynamic_extent ? s_.n - o : c);
353  }
354 
355  constexpr size_type size() const noexcept {
356  return s_.n;
357  }
358 
359  constexpr size_type size_bytes() const noexcept {
360  return s_.n * sizeof(T);
361  }
362 
363  constexpr bool empty() const noexcept {
364  return s_.n == 0;
365  }
366 
367  constexpr reference operator[](size_type i) const {
368  return s_.p[i];
369  }
370 
371  constexpr reference front() const {
372  return *s_.p;
373  }
374 
375  constexpr reference back() const {
376  return s_.p[s_.n - 1];
377  }
378 
379  constexpr pointer data() const noexcept {
380  return s_.p;
381  }
382 
383  constexpr iterator begin() const noexcept {
384  return s_.p;
385  }
386 
387  constexpr iterator end() const noexcept {
388  return s_.p + s_.n;
389  }
390 
391  constexpr reverse_iterator rbegin() const noexcept {
392  return reverse_iterator(s_.p + s_.n);
393  }
394 
395  constexpr reverse_iterator rend() const noexcept {
396  return reverse_iterator(s_.p);
397  }
398 
399  constexpr const_iterator cbegin() const noexcept {
400  return s_.p;
401  }
402 
403  constexpr const_iterator cend() const noexcept {
404  return s_.p + s_.n;
405  }
406 
407  constexpr const_reverse_iterator crbegin() const noexcept {
408  return const_reverse_iterator(s_.p + s_.n);
409  }
410 
411  constexpr const_reverse_iterator crend() const noexcept {
412  return const_reverse_iterator(s_.p);
413  }
414 
415 private:
417 };
418 
419 #if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
420 template<class T, std::size_t E>
421 constexpr std::size_t span<T, E>::extent;
422 #endif
423 
424 #ifdef __cpp_deduction_guides
425 template<class I, class L>
426 span(I*, L) -> span<I>;
427 
428 template<class T, std::size_t N>
429 span(T(&)[N]) -> span<T, N>;
430 
431 template<class T, std::size_t N>
432 span(std::array<T, N>&) -> span<T, N>;
433 
434 template<class T, std::size_t N>
435 span(const std::array<T, N>&) -> span<const T, N>;
436 
437 template<class R>
439 
440 template<class T, std::size_t E>
442 #endif
443 
444 #ifdef __cpp_lib_byte
445 template<class T, std::size_t E>
447 as_bytes(span<T, E> s) noexcept
448 {
449  return span<const std::byte, detail::span_bytes<T,
450  E>::value>(reinterpret_cast<const std::byte*>(s.data()),
451  s.size_bytes());
452 }
453 
454 template<class T, std::size_t E>
455 inline typename std::enable_if<!std::is_const<T>::value,
456  span<std::byte, detail::span_bytes<T, E>::value> >::type
457 as_writable_bytes(span<T, E> s) noexcept
458 {
459  return span<std::byte, detail::span_bytes<T,
460  E>::value>(reinterpret_cast<std::byte*>(s.data()), s.size_bytes());
461 }
462 #endif
463 
464 } /* boost */
465 
466 namespace utils { using boost::span; }
467 
468 #endif
std::size_t size_type
Definition: span.hpp:228
constexpr reverse_iterator rbegin() const noexcept
Definition: span.hpp:391
std::remove_cv< T >::type value_type
Definition: span.hpp:227
constexpr reference operator[](size_type i) const
Definition: span.hpp:367
constexpr iterator end() const noexcept
Definition: span.hpp:387
std::reverse_iterator< const T * > const_reverse_iterator
Definition: span.hpp:237
const T * const_iterator
Definition: span.hpp:235
constexpr const_reverse_iterator crbegin() const noexcept
Definition: span.hpp:407
constexpr std::enable_if< C==dynamic_extent, span< T, detail::span_sub< E, O >::value > >::type subspan() const
Definition: span.hpp:328
T & reference
Definition: span.hpp:232
constexpr span(std::array< U, N > &a) noexcept
Definition: span.hpp:279
constexpr span(R &&r) noexcept(noexcept(boost::data(r)) &&noexcept(r.size()))
Definition: span.hpp:291
constexpr span< T, dynamic_extent > first(size_type c) const
Definition: span.hpp:341
T * iterator
Definition: span.hpp:234
T element_type
Definition: span.hpp:226
constexpr std::enable_if< C !=dynamic_extent, span< T, C > >::type subspan() const
Definition: span.hpp:335
constexpr span(typename std::enable_if< true, T >::type(&a)[N]) noexcept
Definition: span.hpp:273
constexpr const_reverse_iterator crend() const noexcept
Definition: span.hpp:411
constexpr const_iterator cbegin() const noexcept
Definition: span.hpp:399
constexpr span< T, C > last() const
Definition: span.hpp:321
constexpr bool empty() const noexcept
Definition: span.hpp:363
constexpr pointer data() const noexcept
Definition: span.hpp:379
std::ptrdiff_t difference_type
Definition: span.hpp:229
std::reverse_iterator< T * > reverse_iterator
Definition: span.hpp:236
constexpr size_type size_bytes() const noexcept
Definition: span.hpp:359
constexpr span< T, dynamic_extent > subspan(size_type o, size_type c=dynamic_extent) const
Definition: span.hpp:349
T * pointer
Definition: span.hpp:230
detail::span_store< T, E > s_
Definition: span.hpp:416
constexpr span() noexcept
Definition: span.hpp:243
const T * const_pointer
Definition: span.hpp:231
constexpr iterator begin() const noexcept
Definition: span.hpp:383
static constexpr std::size_t extent
Definition: span.hpp:239
constexpr const_iterator cend() const noexcept
Definition: span.hpp:403
constexpr span(const span< U, N > &s) noexcept
Definition: span.hpp:305
constexpr span< T, dynamic_extent > last(size_type c) const
Definition: span.hpp:345
constexpr span< T, C > first() const
Definition: span.hpp:315
constexpr reference front() const
Definition: span.hpp:371
constexpr reference back() const
Definition: span.hpp:375
constexpr reverse_iterator rend() const noexcept
Definition: span.hpp:395
constexpr size_type size() const noexcept
Definition: span.hpp:355
constexpr span(I *f, size_type c)
Definition: span.hpp:249
const T & const_reference
Definition: span.hpp:233
constexpr span(const std::array< U, N > &a) noexcept
Definition: span.hpp:285
constexpr span(I *f, L *l)
Definition: span.hpp:261
std::size_t i
Definition: function.cpp:1030
typename std::remove_cv< typename std::remove_reference< T >::type >::type span_uncvref
Definition: span.hpp:108
decltype(boost::data(std::declval< T & >())) span_ptr
Definition: span.hpp:131
Definition: span.hpp:53
constexpr std::size_t dynamic_extent
Definition: span.hpp:83
constexpr auto data(C &c) noexcept(noexcept(c.data())) -> decltype(c.data())
Definition: span.hpp:57
static constexpr std::size_t value
Definition: span.hpp:213
static constexpr bool value
Definition: span.hpp:97
static constexpr bool value
Definition: span.hpp:102
static constexpr bool value
Definition: span.hpp:92
static constexpr bool value
Definition: span.hpp:184
static constexpr bool value
Definition: span.hpp:144
static constexpr bool value
Definition: span.hpp:155
static constexpr bool value
Definition: span.hpp:178
static constexpr bool value
Definition: span.hpp:122
static constexpr bool value
Definition: span.hpp:167
static constexpr bool value
Definition: span.hpp:112
constexpr span_store(T *p_, std::size_t n_) noexcept
Definition: span.hpp:204
constexpr span_store(T *p_, std::size_t) noexcept
Definition: span.hpp:196
static constexpr std::size_t n
Definition: span.hpp:198
static constexpr std::size_t value
Definition: span.hpp:190
mock_char c
static map_location::direction s
#define f