1 | #pragma once
|
2 |
|
3 | #if __cplusplus >= 202000L
|
4 |
|
5 | #include <span> // use std lib impl
|
6 |
|
7 | namespace souffle {
|
8 | constexpr auto dynamic_extent = std::dynamic_extent;
|
9 |
|
10 | template <typename A, std::size_t E = std::dynamic_extent>
|
11 | using span = std::span<A, E>;
|
12 | } // namespace souffle
|
13 |
|
14 | #else
|
15 |
|
16 | // clang-format off
|
17 | /*
|
18 | This is an implementation of C++20's std::span
|
19 | http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4820.pdf
|
20 | */
|
21 |
|
22 | // Copyright Tristan Brindle 2018.
|
23 | // Distributed under the Boost Software License, Version 1.0.
|
24 | // (See accompanying file ../../LICENSE_1_0.txt or copy at
|
25 | // https://www.boost.org/LICENSE_1_0.txt)
|
26 |
|
27 | #ifndef TCB_SPAN_HPP_INCLUDED
|
28 | #define TCB_SPAN_HPP_INCLUDED
|
29 |
|
30 | #include <array>
|
31 | #include <cstddef>
|
32 | #include <cstdint>
|
33 | #include <type_traits>
|
34 |
|
35 | #ifndef TCB_SPAN_NO_EXCEPTIONS
|
36 | // Attempt to discover whether we're being compiled with exception support
|
37 | #if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND))
|
38 | #define TCB_SPAN_NO_EXCEPTIONS
|
39 | #endif
|
40 | #endif
|
41 |
|
42 | #ifndef TCB_SPAN_NO_EXCEPTIONS
|
43 | #include <cstdio>
|
44 | #include <stdexcept>
|
45 | #endif
|
46 |
|
47 | // Various feature test macros
|
48 |
|
49 | #ifndef TCB_SPAN_NAMESPACE_NAME
|
50 | #define TCB_SPAN_NAMESPACE_NAME tcb
|
51 | #endif
|
52 |
|
53 | #if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
|
54 | #define TCB_SPAN_HAVE_CPP17
|
55 | #endif
|
56 |
|
57 | #if __cplusplus >= 201402L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)
|
58 | #define TCB_SPAN_HAVE_CPP14
|
59 | #endif
|
60 |
|
61 | namespace TCB_SPAN_NAMESPACE_NAME {
|
62 |
|
63 | // Establish default contract checking behavior
|
64 | #if !defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION) && \
|
65 | !defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION) && \
|
66 | !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
|
67 | #if defined(NDEBUG) || !defined(TCB_SPAN_HAVE_CPP14)
|
68 | #define TCB_SPAN_NO_CONTRACT_CHECKING
|
69 | #else
|
70 | #define TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION
|
71 | #endif
|
72 | #endif
|
73 |
|
74 | #if defined(TCB_SPAN_THROW_ON_CONTRACT_VIOLATION)
|
75 | struct contract_violation_error : std::logic_error {
|
76 | explicit contract_violation_error(const char* msg) : std::logic_error(msg)
|
77 | {}
|
78 | };
|
79 |
|
80 | inline void contract_violation(const char* msg)
|
81 | {
|
82 | throw contract_violation_error(msg);
|
83 | }
|
84 |
|
85 | #elif defined(TCB_SPAN_TERMINATE_ON_CONTRACT_VIOLATION)
|
86 | [[noreturn]] inline void contract_violation(const char* /*unused*/)
|
87 | {
|
88 | std::terminate();
|
89 | }
|
90 | #endif
|
91 |
|
92 | #if !defined(TCB_SPAN_NO_CONTRACT_CHECKING)
|
93 | #define TCB_SPAN_STRINGIFY(cond) #cond
|
94 | #define TCB_SPAN_EXPECT(cond) \
|
95 | cond ? (void) 0 : contract_violation("Expected " TCB_SPAN_STRINGIFY(cond))
|
96 | #else
|
97 | #define TCB_SPAN_EXPECT(cond)
|
98 | #endif
|
99 |
|
100 | #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_inline_variables)
|
101 | #define TCB_SPAN_INLINE_VAR inline
|
102 | #else
|
103 | #define TCB_SPAN_INLINE_VAR
|
104 | #endif
|
105 |
|
106 | #if defined(TCB_SPAN_HAVE_CPP14) || \
|
107 | (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
|
108 | #define TCB_SPAN_HAVE_CPP14_CONSTEXPR
|
109 | #endif
|
110 |
|
111 | #if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR)
|
112 | #define TCB_SPAN_CONSTEXPR14 constexpr
|
113 | #else
|
114 | #define TCB_SPAN_CONSTEXPR14
|
115 | #endif
|
116 |
|
117 | #if defined(TCB_SPAN_HAVE_CPP14_CONSTEXPR) && \
|
118 | (!defined(_MSC_VER) || _MSC_VER > 1900)
|
119 | #define TCB_SPAN_CONSTEXPR_ASSIGN constexpr
|
120 | #else
|
121 | #define TCB_SPAN_CONSTEXPR_ASSIGN
|
122 | #endif
|
123 |
|
124 | #if defined(TCB_SPAN_NO_CONTRACT_CHECKING)
|
125 | #define TCB_SPAN_CONSTEXPR11 constexpr
|
126 | #else
|
127 | #define TCB_SPAN_CONSTEXPR11 TCB_SPAN_CONSTEXPR14
|
128 | #endif
|
129 |
|
130 | #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_deduction_guides)
|
131 | #define TCB_SPAN_HAVE_DEDUCTION_GUIDES
|
132 | #endif
|
133 |
|
134 | #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_byte)
|
135 | #define TCB_SPAN_HAVE_STD_BYTE
|
136 | #endif
|
137 |
|
138 | #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_array_constexpr)
|
139 | #define TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC
|
140 | #endif
|
141 |
|
142 | #if defined(TCB_SPAN_HAVE_CONSTEXPR_STD_ARRAY_ETC)
|
143 | #define TCB_SPAN_ARRAY_CONSTEXPR constexpr
|
144 | #else
|
145 | #define TCB_SPAN_ARRAY_CONSTEXPR
|
146 | #endif
|
147 |
|
148 | #ifdef TCB_SPAN_HAVE_STD_BYTE
|
149 | using byte = std::byte;
|
150 | #else
|
151 | using byte = unsigned char;
|
152 | #endif
|
153 |
|
154 | #if defined(TCB_SPAN_HAVE_CPP17)
|
155 | #define TCB_SPAN_NODISCARD [[nodiscard]]
|
156 | #else
|
157 | #define TCB_SPAN_NODISCARD
|
158 | #endif
|
159 |
|
160 | TCB_SPAN_INLINE_VAR constexpr std::size_t dynamic_extent = SIZE_MAX;
|
161 |
|
162 | template <typename ElementType, std::size_t Extent = dynamic_extent>
|
163 | class span;
|
164 |
|
165 | namespace detail {
|
166 |
|
167 | template <typename E, std::size_t S>
|
168 | struct span_storage {
|
169 | constexpr span_storage() noexcept = default;
|
170 |
|
171 | constexpr span_storage(E* p_ptr, std::size_t /*unused*/) noexcept
|
172 | : ptr(p_ptr)
|
173 | {}
|
174 |
|
175 | E* ptr = nullptr;
|
176 | static constexpr std::size_t size = S;
|
177 | };
|
178 |
|
179 | template <typename E>
|
180 | struct span_storage<E, dynamic_extent> {
|
181 | constexpr span_storage() noexcept = default;
|
182 |
|
183 | constexpr span_storage(E* p_ptr, std::size_t p_size) noexcept
|
184 | : ptr(p_ptr), size(p_size)
|
185 | {}
|
186 |
|
187 | E* ptr = nullptr;
|
188 | std::size_t size = 0;
|
189 | };
|
190 |
|
191 | // Reimplementation of C++17 std::size() and std::data()
|
192 | #if defined(TCB_SPAN_HAVE_CPP17) || \
|
193 | defined(__cpp_lib_nonmember_container_access)
|
194 | using std::data;
|
195 | using std::size;
|
196 | #else
|
197 | template <class C>
|
198 | constexpr auto size(const C& c) -> decltype(c.size())
|
199 | {
|
200 | return c.size();
|
201 | }
|
202 |
|
203 | template <class T, std::size_t N>
|
204 | constexpr std::size_t size(const T (&)[N]) noexcept
|
205 | {
|
206 | return N;
|
207 | }
|
208 |
|
209 | template <class C>
|
210 | constexpr auto data(C& c) -> decltype(c.data())
|
211 | {
|
212 | return c.data();
|
213 | }
|
214 |
|
215 | template <class C>
|
216 | constexpr auto data(const C& c) -> decltype(c.data())
|
217 | {
|
218 | return c.data();
|
219 | }
|
220 |
|
221 | template <class T, std::size_t N>
|
222 | constexpr T* data(T (&array)[N]) noexcept
|
223 | {
|
224 | return array;
|
225 | }
|
226 |
|
227 | template <class E>
|
228 | constexpr const E* data(std::initializer_list<E> il) noexcept
|
229 | {
|
230 | return il.begin();
|
231 | }
|
232 | #endif // TCB_SPAN_HAVE_CPP17
|
233 |
|
234 | #if defined(TCB_SPAN_HAVE_CPP17) || defined(__cpp_lib_void_t)
|
235 | using std::void_t;
|
236 | #else
|
237 | template <typename...>
|
238 | using void_t = void;
|
239 | #endif
|
240 |
|
241 | template <typename T>
|
242 | using uncvref_t =
|
243 | typename std::remove_cv<typename std::remove_reference<T>::type>::type;
|
244 |
|
245 | template <typename>
|
246 | struct is_span : std::false_type {};
|
247 |
|
248 | template <typename T, std::size_t S>
|
249 | struct is_span<span<T, S>> : std::true_type {};
|
250 |
|
251 | template <typename>
|
252 | struct is_std_array : std::false_type {};
|
253 |
|
254 | template <typename T, std::size_t N>
|
255 | struct is_std_array<std::array<T, N>> : std::true_type {};
|
256 |
|
257 | template <typename, typename = void>
|
258 | struct has_size_and_data : std::false_type {};
|
259 |
|
260 | template <typename T>
|
261 | struct has_size_and_data<T, void_t<decltype(detail::size(std::declval<T>())),
|
262 | decltype(detail::data(std::declval<T>()))>>
|
263 | : std::true_type {};
|
264 |
|
265 | template <typename C, typename U = uncvref_t<C>>
|
266 | struct is_container {
|
267 | static constexpr bool value =
|
268 | !is_span<U>::value && !is_std_array<U>::value &&
|
269 | !std::is_array<U>::value && has_size_and_data<C>::value;
|
270 | };
|
271 |
|
272 | template <typename T>
|
273 | using remove_pointer_t = typename std::remove_pointer<T>::type;
|
274 |
|
275 | template <typename, typename, typename = void>
|
276 | struct is_container_element_type_compatible : std::false_type {};
|
277 |
|
278 | template <typename T, typename E>
|
279 | struct is_container_element_type_compatible<
|
280 | T, E,
|
281 | typename std::enable_if<
|
282 | !std::is_same<typename std::remove_cv<decltype(
|
283 | detail::data(std::declval<T>()))>::type,
|
284 | void>::value>::type>
|
285 | // HACK: WORKAROUND - GCC 9.2.1 claims `A* (*)[]` is not compatible w/ `A const* (*)[]`.
|
286 | // This seems BS and Clang 10.0 is perfectly happy.
|
287 | // GCC 9.2.1 does, however, agree that `A**` is compatible w/ `A const**`.
|
288 | // Use the `*` test instead of `(*)[]`.
|
289 | : std::is_convertible<
|
290 | remove_pointer_t<decltype(detail::data(std::declval<T>()))>*,
|
291 | E*> {};
|
292 |
|
293 | template <typename, typename = std::size_t>
|
294 | struct is_complete : std::false_type {};
|
295 |
|
296 | template <typename T>
|
297 | struct is_complete<T, decltype(sizeof(T))> : std::true_type {};
|
298 |
|
299 | } // namespace detail
|
300 |
|
301 | template <typename ElementType, std::size_t Extent>
|
302 | class span {
|
303 | static_assert(std::is_object<ElementType>::value,
|
304 | "A span's ElementType must be an object type (not a "
|
305 | "reference type or void)");
|
306 | static_assert(detail::is_complete<ElementType>::value,
|
307 | "A span's ElementType must be a complete type (not a forward "
|
308 | "declaration)");
|
309 | static_assert(!std::is_abstract<ElementType>::value,
|
310 | "A span's ElementType cannot be an abstract class type");
|
311 |
|
312 | using storage_type = detail::span_storage<ElementType, Extent>;
|
313 |
|
314 | public:
|
315 | // constants and types
|
316 | using element_type = ElementType;
|
317 | using value_type = typename std::remove_cv<ElementType>::type;
|
318 | using size_type = std::size_t;
|
319 | using difference_type = std::ptrdiff_t;
|
320 | using pointer = element_type*;
|
321 | using const_pointer = const element_type*;
|
322 | using reference = element_type&;
|
323 | using const_reference = const element_type&;
|
324 | using iterator = pointer;
|
325 | using reverse_iterator = std::reverse_iterator<iterator>;
|
326 |
|
327 | static constexpr size_type extent = Extent;
|
328 |
|
329 | // [span.cons], span constructors, copy, assignment, and destructor
|
330 | template <
|
331 | std::size_t E = Extent,
|
332 | typename std::enable_if<(E == dynamic_extent || E <= 0), int>::type = 0>
|
333 | constexpr span() noexcept // NOLINT : clang-tidy is mistaken. one cannot `default` a template ctor
|
334 | {}
|
335 |
|
336 | TCB_SPAN_CONSTEXPR11 span(pointer ptr, size_type count)
|
337 | : storage_(ptr, count)
|
338 | {
|
339 | TCB_SPAN_EXPECT(extent == dynamic_extent || count == extent);
|
340 | }
|
341 |
|
342 | TCB_SPAN_CONSTEXPR11 span(pointer first_elem, pointer last_elem)
|
343 | : storage_(first_elem, last_elem - first_elem)
|
344 | {
|
345 | TCB_SPAN_EXPECT(extent == dynamic_extent ||
|
346 | last_elem - first_elem ==
|
347 | static_cast<std::ptrdiff_t>(extent));
|
348 | }
|
349 |
|
350 | template <std::size_t N, std::size_t E = Extent,
|
351 | typename std::enable_if<
|
352 | (E == dynamic_extent || N == E) &&
|
353 | detail::is_container_element_type_compatible<
|
354 | element_type (&)[N], ElementType>::value,
|
355 | int>::type = 0>
|
356 | constexpr span(element_type (&arr)[N]) noexcept : storage_(arr, N)
|
357 | {}
|
358 |
|
359 | template <std::size_t N, std::size_t E = Extent,
|
360 | typename std::enable_if<
|
361 | (E == dynamic_extent || N == E) &&
|
362 | detail::is_container_element_type_compatible<
|
363 | std::array<value_type, N>&, ElementType>::value,
|
364 | int>::type = 0>
|
365 | TCB_SPAN_ARRAY_CONSTEXPR span(std::array<value_type, N>& arr) noexcept
|
366 | : storage_(arr.data(), N)
|
367 | {}
|
368 |
|
369 | template <std::size_t N, std::size_t E = Extent,
|
370 | typename std::enable_if<
|
371 | (E == dynamic_extent || N == E) &&
|
372 | detail::is_container_element_type_compatible<
|
373 | const std::array<value_type, N>&, ElementType>::value,
|
374 | int>::type = 0>
|
375 | TCB_SPAN_ARRAY_CONSTEXPR span(const std::array<value_type, N>& arr) noexcept
|
376 | : storage_(arr.data(), N)
|
377 | {}
|
378 |
|
379 | template <
|
380 | typename Container, std::size_t E = Extent,
|
381 | typename std::enable_if<
|
382 | E == dynamic_extent && detail::is_container<Container>::value &&
|
383 | detail::is_container_element_type_compatible<
|
384 | Container&, ElementType>::value,
|
385 | int>::type = 0>
|
386 | constexpr span(Container& cont)
|
387 | : storage_(detail::data(cont), detail::size(cont))
|
388 | {}
|
389 |
|
390 | template <
|
391 | typename Container, std::size_t E = Extent,
|
392 | typename std::enable_if<
|
393 | E == dynamic_extent && detail::is_container<Container>::value &&
|
394 | detail::is_container_element_type_compatible<
|
395 | const Container&, ElementType>::value,
|
396 | int>::type = 0>
|
397 | constexpr span(const Container& cont)
|
398 | : storage_(detail::data(cont), detail::size(cont))
|
399 | {}
|
400 |
|
401 | constexpr span(const span& other) noexcept = default;
|
402 |
|
403 | template <typename OtherElementType, std::size_t OtherExtent,
|
404 | typename std::enable_if<
|
405 | (Extent == OtherExtent || Extent == dynamic_extent) &&
|
406 | std::is_convertible<OtherElementType (*)[],
|
407 | ElementType (*)[]>::value,
|
408 | int>::type = 0>
|
409 | constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
|
410 | : storage_(other.data(), other.size())
|
411 | {}
|
412 |
|
413 | ~span() noexcept = default;
|
414 |
|
415 | TCB_SPAN_CONSTEXPR_ASSIGN span&
|
416 | operator=(const span& other) noexcept = default;
|
417 |
|
418 | // [span.sub], span subviews
|
419 | template <std::size_t Count>
|
420 | TCB_SPAN_CONSTEXPR11 span<element_type, Count> first() const
|
421 | {
|
422 | TCB_SPAN_EXPECT(Count <= size());
|
423 | return {data(), Count};
|
424 | }
|
425 |
|
426 | template <std::size_t Count>
|
427 | TCB_SPAN_CONSTEXPR11 span<element_type, Count> last() const
|
428 | {
|
429 | TCB_SPAN_EXPECT(Count <= size());
|
430 | return {data() + (size() - Count), Count};
|
431 | }
|
432 |
|
433 | template <std::size_t Offset, std::size_t Count = dynamic_extent>
|
434 | using subspan_return_t =
|
435 | span<ElementType, Count != dynamic_extent
|
436 | ? Count
|
437 | : (Extent != dynamic_extent ? Extent - Offset
|
438 | : dynamic_extent)>;
|
439 |
|
440 | template <std::size_t Offset, std::size_t Count = dynamic_extent>
|
441 | TCB_SPAN_CONSTEXPR11 subspan_return_t<Offset, Count> subspan() const
|
442 | {
|
443 | TCB_SPAN_EXPECT(Offset <= size() &&
|
444 | (Count == dynamic_extent || Offset + Count <= size()));
|
445 | return {data() + Offset,
|
446 | Count != dynamic_extent ? Count : size() - Offset};
|
447 | }
|
448 |
|
449 | TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
|
450 | first(size_type count) const
|
451 | {
|
452 | TCB_SPAN_EXPECT(count <= size());
|
453 | return {data(), count};
|
454 | }
|
455 |
|
456 | TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
|
457 | last(size_type count) const
|
458 | {
|
459 | TCB_SPAN_EXPECT(count <= size());
|
460 | return {data() + (size() - count), count};
|
461 | }
|
462 |
|
463 | TCB_SPAN_CONSTEXPR11 span<element_type, dynamic_extent>
|
464 | subspan(size_type offset, size_type count = dynamic_extent) const
|
465 | {
|
466 | TCB_SPAN_EXPECT(offset <= size() &&
|
467 | (count == dynamic_extent || offset + count <= size()));
|
468 | return {data() + offset,
|
469 | count == dynamic_extent ? size() - offset : count};
|
470 | }
|
471 |
|
472 | // [span.obs], span observers
|
473 | constexpr size_type size() const noexcept { return storage_.size; }
|
474 |
|
475 | constexpr size_type size_bytes() const noexcept
|
476 | {
|
477 | return size() * sizeof(element_type);
|
478 | }
|
479 |
|
480 | TCB_SPAN_NODISCARD constexpr bool empty() const noexcept
|
481 | {
|
482 | return size() == 0;
|
483 | }
|
484 |
|
485 | // [span.elem], span element access
|
486 | TCB_SPAN_CONSTEXPR11 reference operator[](size_type idx) const
|
487 | {
|
488 | TCB_SPAN_EXPECT(idx < size());
|
489 | return *(data() + idx);
|
490 | }
|
491 |
|
492 | TCB_SPAN_CONSTEXPR11 reference front() const
|
493 | {
|
494 | TCB_SPAN_EXPECT(!empty());
|
495 | return *data();
|
496 | }
|
497 |
|
498 | TCB_SPAN_CONSTEXPR11 reference back() const
|
499 | {
|
500 | TCB_SPAN_EXPECT(!empty());
|
501 | return *(data() + (size() - 1));
|
502 | }
|
503 |
|
504 | constexpr pointer data() const noexcept { return storage_.ptr; }
|
505 |
|
506 | // [span.iterators], span iterator support
|
507 | constexpr iterator begin() const noexcept { return data(); }
|
508 |
|
509 | constexpr iterator end() const noexcept { return data() + size(); }
|
510 |
|
511 | TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rbegin() const noexcept
|
512 | {
|
513 | return reverse_iterator(end());
|
514 | }
|
515 |
|
516 | TCB_SPAN_ARRAY_CONSTEXPR reverse_iterator rend() const noexcept
|
517 | {
|
518 | return reverse_iterator(begin());
|
519 | }
|
520 |
|
521 | private:
|
522 | storage_type storage_{};
|
523 | };
|
524 |
|
525 | #ifdef TCB_SPAN_HAVE_DEDUCTION_GUIDES
|
526 |
|
527 | /* Deduction Guides */
|
528 | template <class T, std::size_t N>
|
529 | span(T (&)[N])->span<T, N>;
|
530 |
|
531 | template <class T, std::size_t N>
|
532 | span(std::array<T, N>&)->span<T, N>;
|
533 |
|
534 | template <class T, std::size_t N>
|
535 | span(const std::array<T, N>&)->span<const T, N>;
|
536 |
|
537 | template <class Container>
|
538 | span(Container&)->span<typename Container::value_type>;
|
539 |
|
540 | template <class Container>
|
541 | span(const Container&)->span<const typename Container::value_type>;
|
542 |
|
543 | #endif // TCB_HAVE_DEDUCTION_GUIDES
|
544 |
|
545 | template <typename ElementType, std::size_t Extent>
|
546 | constexpr span<ElementType, Extent>
|
547 | make_span(span<ElementType, Extent> s) noexcept
|
548 | {
|
549 | return s;
|
550 | }
|
551 |
|
552 | template <typename T, std::size_t N>
|
553 | constexpr span<T, N> make_span(T (&arr)[N]) noexcept
|
554 | {
|
555 | return {arr};
|
556 | }
|
557 |
|
558 | template <typename T, std::size_t N>
|
559 | TCB_SPAN_ARRAY_CONSTEXPR span<T, N> make_span(std::array<T, N>& arr) noexcept
|
560 | {
|
561 | return {arr};
|
562 | }
|
563 |
|
564 | template <typename T, std::size_t N>
|
565 | TCB_SPAN_ARRAY_CONSTEXPR span<const T, N>
|
566 | make_span(const std::array<T, N>& arr) noexcept
|
567 | {
|
568 | return {arr};
|
569 | }
|
570 |
|
571 | template <typename Container>
|
572 | constexpr span<typename Container::value_type> make_span(Container& cont)
|
573 | {
|
574 | return {cont};
|
575 | }
|
576 |
|
577 | template <typename Container>
|
578 | constexpr span<const typename Container::value_type>
|
579 | make_span(const Container& cont)
|
580 | {
|
581 | return {cont};
|
582 | }
|
583 |
|
584 | template <typename ElementType, std::size_t Extent>
|
585 | span<const byte, ((Extent == dynamic_extent) ? dynamic_extent
|
586 | : sizeof(ElementType) * Extent)>
|
587 | as_bytes(span<ElementType, Extent> s) noexcept
|
588 | {
|
589 | return {reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
|
590 | }
|
591 |
|
592 | template <
|
593 | class ElementType, std::size_t Extent,
|
594 | typename std::enable_if<!std::is_const<ElementType>::value, int>::type = 0>
|
595 | span<byte, ((Extent == dynamic_extent) ? dynamic_extent
|
596 | : sizeof(ElementType) * Extent)>
|
597 | as_writable_bytes(span<ElementType, Extent> s) noexcept
|
598 | {
|
599 | return {reinterpret_cast<byte*>(s.data()), s.size_bytes()};
|
600 | }
|
601 |
|
602 | template <std::size_t N, typename E, std::size_t S>
|
603 | constexpr auto get(span<E, S> s) -> decltype(s[N])
|
604 | {
|
605 | return s[N];
|
606 | }
|
607 |
|
608 | } // namespace TCB_SPAN_NAMESPACE_NAME
|
609 |
|
610 | namespace std {
|
611 |
|
612 | // see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82716
|
613 | // libc++: https://reviews.llvm.org/D55466#1325498
|
614 | // `libc++` changed to use `struct`
|
615 | // spec: http://eel.is/c++draft/tuple.helper
|
616 | // Spec says to use `struct`.
|
617 | // MSVC: Has different ABI for `class`/`struct`.
|
618 | // Defined `tuple_size` as `class`.
|
619 | #if defined(_MSC_VER)
|
620 | #define TCB_SPAN_TUPLE_SIZE_KIND class
|
621 | #else
|
622 | #define TCB_SPAN_TUPLE_SIZE_KIND struct
|
623 | #endif
|
624 |
|
625 | #if defined(__clang__)
|
626 | #pragma clang diagnostic push
|
627 | #pragma clang diagnostic ignored "-Wmismatched-tags"
|
628 | #endif
|
629 |
|
630 | template <typename ElementType, std::size_t Extent>
|
631 | TCB_SPAN_TUPLE_SIZE_KIND tuple_size<TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>>
|
632 | : public integral_constant<std::size_t, Extent> {};
|
633 |
|
634 | template <typename ElementType>
|
635 | TCB_SPAN_TUPLE_SIZE_KIND tuple_size<TCB_SPAN_NAMESPACE_NAME::span<
|
636 | ElementType, TCB_SPAN_NAMESPACE_NAME::dynamic_extent>>; // not defined
|
637 |
|
638 | template <std::size_t I, typename ElementType, std::size_t Extent>
|
639 | TCB_SPAN_TUPLE_SIZE_KIND tuple_element<I, TCB_SPAN_NAMESPACE_NAME::span<ElementType, Extent>> {
|
640 | public:
|
641 | static_assert(Extent != TCB_SPAN_NAMESPACE_NAME::dynamic_extent &&
|
642 | I < Extent,
|
643 | "");
|
644 | using type = ElementType;
|
645 | };
|
646 |
|
647 | #if defined(__clang__)
|
648 | #pragma clang diagnostic pop
|
649 | #endif
|
650 |
|
651 | #undef TCB_SPAN_TUPLE_SIZE_KIND
|
652 |
|
653 | } // end namespace std
|
654 |
|
655 | #endif // TCB_SPAN_HPP_INCLUDED
|
656 |
|
657 | // clang-format on
|
658 |
|
659 | namespace souffle {
|
660 | constexpr auto dynamic_extent = tcb::dynamic_extent;
|
661 |
|
662 | template <typename A, std::size_t E = tcb::dynamic_extent>
|
663 | using span = tcb::span<A, E>;
|
664 | } // namespace souffle
|
665 |
|
666 | #endif
|