Thorin 1.9.0
The Higher ORder INtermediate representation
Loading...
Searching...
No Matches
span.h
Go to the documentation of this file.
1#pragma once
2
3#include <span>
4
5namespace thorin {
6
7/// Something which behaves like `std::vector` or `std::array`.
8template<class Vec>
9concept Vectorlike = requires(Vec vec) {
10 typename Vec::value_type;
11 vec.size();
12 vec.data();
13};
14
15/// This is a thin wrapper for [`std::span<T, N>`](https://en.cppreference.com/w/cpp/container/span)
16/// with the following additional features:
17/// * Constructor with `std::initializer_list` (C++26 will get this ...)
18/// * Constructor for any compatible Vectorlike argument
19/// * rsubspan (reverse subspan)
20/// * structured binding, if `N != std::dynamic_extent:`
21/// ```
22/// void f(Span<int, 3> span) {
23/// auto& [a, b, c] = span;
24/// b = 23;
25/// // ...
26/// }
27/// ```
28template<class T, size_t N = std::dynamic_extent> class Span : public std::span<T, N> {
29public:
30 using Base = std::span<T, N>;
31
32 /// @name Constructors
33 ///@{
34 using Base::Base;
35 explicit(N != std::dynamic_extent) constexpr Span(std::initializer_list<T> init) noexcept
36 : Base(std::begin(init), std::ranges::distance(init)) {}
37 constexpr Span(std::span<T, N> span) noexcept
38 : Base(span) {}
39 template<Vectorlike Vec> requires(std::is_same_v<typename Vec::value_type, T>)
40 explicit(N != std::dynamic_extent) constexpr Span(Vec& vec)
41 : Base(vec.data(), vec.size()) {}
42 template<Vectorlike Vec> requires(std::is_same_v<std::add_const_t<typename Vec::value_type>, std::add_const_t<T>>)
43 explicit(N != std::dynamic_extent) constexpr Span(const Vec& vec)
44 : Base(vec.data(), vec.size()) {}
45 constexpr explicit Span(typename Base::pointer p)
46 : Base(p, N) {
47 static_assert(N != std::dynamic_extent);
48 }
49 ///@}
50
51 /// @name subspan
52 ///@{
53 /// Wrappers for `std::span::subspan` that return a `thorin::Span`.
54 constexpr Span<T, std::dynamic_extent> subspan(size_t i, size_t n = std::dynamic_extent) const {
55 return Base::subspan(i, n);
56 }
57 constexpr Span<T, std::dynamic_extent> rsubspan(size_t i, size_t n = std::dynamic_extent) const {
58 return n != std::dynamic_extent ? subspan(Base::size() - i - n, n) : subspan(0, Base::size() - i);
59 }
60 ///@}
61
62 /// @name rsubspan
63 ///@{
64 /// Similar to Span::subspan but in *reverse*:
65 /// `span.rsubspan(3, 5)` removes the last 3 elements and while picking 5 elements onwards from there.
66 /// E.g.: If `span` points to `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`, then the result will point to `2, 3, 4, 5, 6`.
67 template<size_t i, size_t n = std::dynamic_extent>
68 constexpr Span<T, n != std::dynamic_extent ? n : (N != std::dynamic_extent ? N - i : std::dynamic_extent)>
69 subspan() const {
70 return Base::template subspan<i, n>();
71 }
72
73 template<size_t i, size_t n = std::dynamic_extent>
74 constexpr Span<T, n != std::dynamic_extent ? n : (N != std::dynamic_extent ? N - i : std::dynamic_extent)>
75 rsubspan() const {
76 if constexpr (n != std::dynamic_extent)
77 return Span<T, n>(Base::data() + Base::size() - i - n);
78 else if constexpr (N != std::dynamic_extent)
79 return Span<T, N - i>(Base::data());
80 else
81 return Span<T, std::dynamic_extent>(Base::data(), Base::size() - i);
82 }
83 ///@}
84};
85
86static_assert(std::ranges::contiguous_range<Span<int>>);
87
88template<class T, size_t N = std::dynamic_extent> using View = Span<const T, N>;
89
90/// @name Deduction Guides
91///@{
92template<class I, class E> Span(I, E) -> Span<std::remove_reference_t<std::iter_reference_t<I>>>;
93template<class T, size_t N> Span(T (&)[N]) -> Span<T, N>;
94template<class T, size_t N> Span(std::array<T, N>&) -> Span<T, N>;
95template<class T, size_t N> Span(const std::array<T, N>&) -> Span<const T, N>;
99///@}
100
101} // namespace thorin
102
103namespace std {
104/// @name Structured Binding Support for Span
105///@{
106template<class T, size_t N> struct tuple_size<thorin::Span<T, N>> : std::integral_constant<size_t, N> {};
107
108template<size_t I, class T, size_t N> struct tuple_element<I, thorin::Span<T, N>> {
110};
111
112template<size_t I, class T, size_t N> constexpr decltype(auto) get(thorin::Span<T, N> span) { return (span[I]); }
113///@}
114} // namespace std
This is a thin wrapper for std::span<T, N> with the following additional features:
Definition span.h:28
constexpr Span(typename Base::pointer p)
Definition span.h:45
std::span< T, N > Base
Definition span.h:30
constexpr Span< T, n !=std::dynamic_extent ? n :(N !=std::dynamic_extent ? N - i :std::dynamic_extent)> subspan() const
Definition span.h:69
constexpr Span(std::span< T, N > span) noexcept
Definition span.h:37
constexpr Span< T, n !=std::dynamic_extent ? n :(N !=std::dynamic_extent ? N - i :std::dynamic_extent)> rsubspan() const
Definition span.h:75
constexpr Span< T, std::dynamic_extent > subspan(size_t i, size_t n=std::dynamic_extent) const
Definition span.h:54
constexpr Span< T, std::dynamic_extent > rsubspan(size_t i, size_t n=std::dynamic_extent) const
Definition span.h:57
Something which behaves like std::vector or std::array.
Definition span.h:9
Definition span.h:103
typename thorin::Span< T, N >::reference type
Definition span.h:109
constexpr decltype(auto) get(thorin::Span< T, N > span)
Definition span.h:112
Definition cfg.h:11