Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
span.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <sysio/vm/exceptions.hpp>
4
5#include <array>
6#include <cstdint>
7#include <limits>
8#include <type_traits>
9
10namespace sysio { namespace vm {
11 inline static constexpr std::size_t dynamic_extent = std::numeric_limits<std::size_t>::max();
12 // TODO after C++20 use std::span as fundamental type
13 template <typename T, std::size_t Extent = dynamic_extent>
14 class span {
15 static_assert( Extent == 1 || Extent == dynamic_extent,
16 "only a static extent of 1 is currently available" );
17 public:
18 using element_type = T;
19 using value_type = std::remove_cv_t<T>;
20 using size_type = std::size_t;
21 using difference_type = std::ptrdiff_t;
22 using pointer = T*;
23 using const_pointer = const T*;
24 using reference = T&;
25 using const_reference = const T&;
26 using iterator = T*;
27 using reverse_iterator = std::reverse_iterator<iterator>;
28 static constexpr std::size_t extent = Extent;
29
30 template<std::size_t E = Extent, typename Enable = std::enable_if_t<E == dynamic_extent || E == 0>>
31 constexpr span() noexcept : first_elem(nullptr), last_elem(nullptr) {}
32
33 // Non-conforming: Only allows pointers, not any contiguous iterator.
34 // Implementing a conforming version of this constructor requires C++20.
35 inline constexpr span(pointer first, std::size_t len) : first_elem(first), last_elem(first + len) {
36 SYS_VM_ASSERT(Extent == dynamic_extent || Extent == size(), span_exception, "Wrong size for span with static extent");
37 }
38 inline constexpr span(pointer first, pointer last) : first_elem(first), last_elem(last) {
39 SYS_VM_ASSERT(last >= first, span_exception, "last iterator < first iterator");
40 SYS_VM_ASSERT(Extent == dynamic_extent || Extent == size(), span_exception, "Wrong size for span with static extent");
41 }
42
43 template <std::size_t N, typename Enable = std::enable_if_t<(Extent == dynamic_extent || N == Extent)>>
44 inline constexpr span(T (&arr)[N]) noexcept : first_elem(&arr[0]), last_elem(&arr[0] + N) {}
45
46 template <typename U, std::size_t N,
47 typename Enable = std::enable_if_t<(Extent == dynamic_extent || N == Extent) && std::is_convertible_v<U(*)[], T(*)[]>>>
48 inline constexpr span(std::array<U, N>& arr) noexcept : first_elem(arr.data()), last_elem(arr.data() + N) {}
49
50 template <typename U, std::size_t N,
51 typename Enable = std::enable_if_t<(Extent == dynamic_extent || N == Extent) && std::is_convertible_v<const U(*)[], T(*)[]>>>
52 inline constexpr span(const std::array<U, N>& arr) noexcept : first_elem(arr.data()), last_elem(arr.data() + N) {}
53
54 // Not implemented:
55 // template<typename R> span(R&&);
56 // template<typename U, typename E> span(const span<U, E>&);
57
58 inline constexpr span(const span&) = default;
59 inline constexpr span(span&&) = default;
60 inline constexpr span& operator=(const span&) = default;
61 inline constexpr span& operator=(span&&) = default;
62
63 inline constexpr iterator begin() const noexcept { return first_elem; }
64 inline constexpr iterator end() const noexcept { return last_elem; }
65 inline constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{last_elem}; }
66 inline constexpr reverse_iterator rend() const noexcept { return reverse_iterator{first_elem}; }
67
68 inline constexpr T& front() const { return *first_elem; }
69 inline constexpr T& back() const { return *(last_elem - 1); }
70 inline constexpr T& operator[](std::size_t n) const { return first_elem[n]; }
71
72 inline constexpr T* data() const noexcept { return first_elem; }
73 inline constexpr std::size_t size() const noexcept { return last_elem - first_elem; }
74 inline constexpr std::size_t size_bytes() const noexcept { return size() * sizeof(T); }
75 inline constexpr bool empty() const noexcept { return size() == 0; }
76
77 inline constexpr span<T, dynamic_extent> first(std::size_t len) const {
78 SYS_VM_ASSERT(len <= size(), span_exception, "length overflows span");
79 return {first_elem, first_elem + len};
80 }
81
82 inline constexpr span<T, dynamic_extent> last(std::size_t len) const {
83 SYS_VM_ASSERT(len <= size(), span_exception, "length underflows span");
84 return {last_elem - len, last_elem};
85 }
86
87 inline constexpr span<T, dynamic_extent> subspan(std::size_t offset, std::size_t len = dynamic_extent) const {
88 if(len == dynamic_extent) len = size() - offset;
89 SYS_VM_ASSERT(first_elem + offset + len <= last_elem, span_exception, "length overflows span");
90 return {first_elem + offset, len};
91 }
92
93 private:
94 iterator first_elem;
95 iterator last_elem;
96 };
97
98 // No deduction guides
99
100 namespace detail {
101 template <typename T>
102 constexpr std::true_type is_span_type(span<T>) { return {}; }
103 template <typename T>
104 constexpr std::false_type is_span_type(T) { return {}; }
105 } // ns sysio::vm::detail
106
107 template <typename T>
108 constexpr inline static bool is_span_type_v = std::is_same_v<decltype(detail::is_span_type(std::declval<T>())), std::true_type>;
109
110}} // ns sysio::vm
const T * const_pointer
Definition span.hpp:23
constexpr std::size_t size_bytes() const noexcept
Definition span.hpp:74
constexpr span(const span &)=default
static constexpr std::size_t extent
Definition span.hpp:28
constexpr iterator begin() const noexcept
Definition span.hpp:63
constexpr span< T, dynamic_extent > last(std::size_t len) const
Definition span.hpp:82
constexpr span(span &&)=default
constexpr T & front() const
Definition span.hpp:68
constexpr std::size_t size() const noexcept
Definition span.hpp:73
constexpr span< T, dynamic_extent > subspan(std::size_t offset, std::size_t len=dynamic_extent) const
Definition span.hpp:87
constexpr T * data() const noexcept
Definition span.hpp:72
constexpr reverse_iterator rend() const noexcept
Definition span.hpp:66
constexpr T & operator[](std::size_t n) const
Definition span.hpp:70
constexpr span(const std::array< U, N > &arr) noexcept
Definition span.hpp:52
constexpr span(std::array< U, N > &arr) noexcept
Definition span.hpp:48
constexpr T & back() const
Definition span.hpp:69
constexpr reverse_iterator rbegin() const noexcept
Definition span.hpp:65
constexpr span< T, dynamic_extent > first(std::size_t len) const
Definition span.hpp:77
constexpr iterator end() const noexcept
Definition span.hpp:64
constexpr span(pointer first, std::size_t len)
Definition span.hpp:35
std::size_t size_type
Definition span.hpp:20
constexpr span(pointer first, pointer last)
Definition span.hpp:38
constexpr span & operator=(const span &)=default
constexpr span & operator=(span &&)=default
constexpr span() noexcept
Definition span.hpp:31
constexpr bool empty() const noexcept
Definition span.hpp:75
std::remove_cv_t< T > value_type
Definition span.hpp:19
constexpr span(T(&arr)[N]) noexcept
Definition span.hpp:44
std::ptrdiff_t difference_type
Definition span.hpp:21
std::reverse_iterator< iterator > reverse_iterator
Definition span.hpp:27
const T & const_reference
Definition span.hpp:25
constexpr std::true_type is_span_type(span< T >)
Definition span.hpp:102
#define T(meth, val, expected)
const int N
Definition quantize.cpp:54
#define SYS_VM_ASSERT(expr, exc_type, msg)
Definition exceptions.hpp:8
Definition dtoa.c:306
size_t len