| 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
|