The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
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>
28namespace utils { using std::span; }
29
30// Boost 1.78 or later
31#elif BOOST_VERSION >= 107800
32
33#include <boost/core/span.hpp>
34namespace utils { using boost::span; }
35
36// Full manual fallback, copied from Boost with some tweaks
37#else
38
39/*
40Copyright 2019-2023 Glen Joseph Fernandes
41(glenjofe@gmail.com)
42
43Distributed 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
53namespace boost {
54
55template<class C>
56inline constexpr auto
57data(C& c) noexcept(noexcept(c.data())) -> decltype(c.data())
58{
59 return c.data();
60}
61
62template<class C>
63inline constexpr auto
64data(const C& c) noexcept(noexcept(c.data())) -> decltype(c.data())
65{
66 return c.data();
67}
68
69template<class T, std::size_t N>
70inline constexpr T*
71data(T(&a)[N]) noexcept
72{
73 return a;
74}
75
76template<class T>
77inline constexpr const T*
78data(std::initializer_list<T> l) noexcept
79{
80 return l.begin();
81}
82
83constexpr std::size_t dynamic_extent = static_cast<std::size_t>(-1);
84
85template<class T, std::size_t E = dynamic_extent>
86class span;
87
88namespace detail {
89
90template<class U, class T>
92 static constexpr bool value = std::is_convertible<U(*)[], T(*)[]>::value;
93};
94
95template<std::size_t E, std::size_t N>
97 static constexpr bool value = E == boost::dynamic_extent || E == N;
98};
99
100template<class T, std::size_t E, class U, std::size_t N>
105
106template<class T>
107using span_uncvref = typename std::remove_cv<typename
108 std::remove_reference<T>::type>::type;
109
110template<class>
112 static constexpr bool value = false;
113};
114
115template<class T, std::size_t E>
116struct span_is_span<boost::span<T, E> > {
117 static constexpr bool value = true;
118};
119
120template<class T>
122 static constexpr bool value = false;
123};
124
125template<class T, std::size_t N>
126struct span_is_array<std::array<T, N> > {
127 static constexpr bool value = true;
128};
129
130template<class T>
131using span_ptr = decltype(boost::data(std::declval<T&>()));
132
133template<class, class = void>
134struct span_data { };
135
136template<class T>
137struct 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
142template<class, class, class = void>
144 static constexpr bool value = false;
145};
146
147template<class R, class T>
148struct 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
153template<class, class = void>
155 static constexpr bool value = false;
156};
157
158template<class R>
159struct 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
165template<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
176template<std::size_t E, std::size_t N>
178 static constexpr bool value = E == boost::dynamic_extent ||
180};
181
182template<class T, std::size_t E, class U, std::size_t N>
187
188template<std::size_t E, std::size_t O>
189struct span_sub {
190 static constexpr std::size_t value = E == boost::dynamic_extent ?
191 boost::dynamic_extent : E - O;
192};
193
194template<class T, std::size_t E>
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
202template<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
211template<class T, std::size_t E>
213 static constexpr std::size_t value = sizeof(T) * E;
214};
215
216template<class T>
218 static constexpr std::size_t value = boost::dynamic_extent;
219};
220
221} /* detail */
222
223template<class T, std::size_t E>
224class span {
225public:
226 typedef T element_type;
227 typedef typename std::remove_cv<T>::type value_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,
242 typename std::enable_if<N == dynamic_extent || N == 0, int>::type = 0>
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,
335 span<T, C> >::type subspan() const {
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
415private:
417};
418
419#if defined(BOOST_NO_CXX17_INLINE_VARIABLES)
420template<class T, std::size_t E>
421constexpr std::size_t span<T, E>::extent;
422#endif
423
424#ifdef __cpp_deduction_guides
425template<class I, class L>
426span(I*, L) -> span<I>;
427
428template<class T, std::size_t N>
429span(T(&)[N]) -> span<T, N>;
430
431template<class T, std::size_t N>
432span(std::array<T, N>&) -> span<T, N>;
433
434template<class T, std::size_t N>
435span(const std::array<T, N>&) -> span<const T, N>;
436
437template<class R>
439
440template<class T, std::size_t E>
442#endif
443
444#ifdef __cpp_lib_byte
445template<class T, std::size_t E>
447as_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
454template<class T, std::size_t E>
455inline typename std::enable_if<!std::is_const<T>::value,
456 span<std::byte, detail::span_bytes<T, E>::value> >::type
457as_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
466namespace 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 std::enable_if< C!=dynamic_extent, span< T, C > >::type subspan() const
Definition span.hpp:335
constexpr const_reverse_iterator crbegin() const noexcept
Definition span.hpp:407
T & reference
Definition span.hpp:232
constexpr std::enable_if< C==dynamic_extent, span< T, detail::span_sub< E, O >::value > >::type subspan() const
Definition span.hpp:328
constexpr span< T, dynamic_extent > last(size_type c) const
Definition span.hpp:345
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
T * iterator
Definition span.hpp:234
T element_type
Definition span.hpp:226
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 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
T * pointer
Definition span.hpp:230
constexpr span< T, C > first() const
Definition span.hpp:315
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 reference front() const
Definition span.hpp:371
constexpr span< T, C > last() const
Definition span.hpp:321
constexpr span< T, dynamic_extent > first(size_type c) const
Definition span.hpp:341
constexpr reference back() const
Definition span.hpp:375
constexpr reverse_iterator rend() const noexcept
Definition span.hpp:395
constexpr span< T, dynamic_extent > subspan(size_type o, size_type c=dynamic_extent) const
Definition span.hpp:349
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
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
STL namespace.
std::string_view data
Definition picture.cpp:188
std::unique_ptr< MIX_Audio, decltype(&MIX_DestroyAudio)> value
Definition sound.cpp:139
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
static map_location::direction s
#define i
#define f
#define c