FE
0.13.1
Header-only C++ frontend library
Toggle main menu visibility
Loading...
Searching...
No Matches
span.h
Go to the documentation of this file.
1
#pragma once
2
3
#include <array>
4
#include <iterator>
5
#include <ranges>
6
#include <span>
7
#include <type_traits>
8
9
namespace
fe
{
10
11
/// Something which behaves like `std::vector` or `std::array`.
12
template
<
class
Vec>
13
concept
Vectorlike
=
requires
(Vec vec) {
14
typename
Vec::value_type;
15
vec.size();
16
vec.data();
17
};
18
19
/// This is a thin wrapper for [`std::span<T, N>`](https://en.cppreference.com/w/cpp/container/span)
20
/// with the following additional features:
21
/// * Constructor with `std::initializer_list` (C++26 will get this ...)
22
/// * Constructor for any compatible Vectorlike argument
23
/// * rsubspan (reverse subspan)
24
/// * structured binding, if `N != std::dynamic_extent:`
25
/// ```
26
/// void f(Span<int, 3> span) {
27
/// auto& [a, b, c] = span;
28
/// b = 23;
29
/// // ...
30
/// }
31
/// ```
32
template
<
class
T,
size_t
N = std::dynamic_extent>
33
class
Span
:
public
std::span<T, N> {
34
public
:
35
using
Base
= std::span<T, N>;
36
constexpr
static
auto
D
= std::dynamic_extent;
37
38
using
Base::data;
39
using
Base::empty;
40
using
Base::size;
41
42
/// @name Constructors
43
///@{
44
using
Base::Base;
45
explicit
(N !=
D
)
constexpr
Span
(std::initializer_list<T> init) noexcept
46
:
Base
(std::begin(init), std::ranges::distance(init)) {}
47
constexpr
Span
(std::span<T, N>
span
) noexcept
48
:
Base
(
span
) {}
49
template
<Vectorlike Vec>
50
requires
(std::is_same_v<typename Vec::value_type, T> && !std::is_const_v<Vec>)
51
explicit
(N !=
D
)
constexpr
Span
(Vec& vec)
noexcept
(
noexcept
(vec.data()) &&
noexcept
(vec.size()))
52
:
Base
(vec.data(), vec.size()) {}
53
template
<Vectorlike Vec>
54
requires
(std::is_const_v<T> && std::is_same_v<std::add_const_t<typename Vec::value_type>, T>)
55
explicit
(N !=
D
)
constexpr
Span
(
const
Vec& vec)
noexcept
(
noexcept
(vec.data()) &&
noexcept
(vec.size()))
56
:
Base
(vec.data(), vec.size()) {}
57
constexpr
explicit
Span
(
typename
Base::pointer p) noexcept
58
:
Base
(p, N) {
59
static_assert
(N !=
D
);
60
}
61
///@}
62
63
/// @name subspan
64
/// Wrappers for `std::span::subspan` that return a
65
/// `fe::Span`. Example: If `span` points to `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`, then
66
/// * `span.subspan<2, 5>()` and `span.subspan(2, 5)` will point to `2, 3, 4, 5, 6`.
67
/// * `span.subspan<2>()` and `span.subspan(2)` will point to `2, 3, 4, 5, 6, 7, 8, 9`.
68
///@{
69
[[nodiscard]]
constexpr
Span<T, D>
subspan
(
size_t
i,
size_t
n =
D
)
const
noexcept
{
return
Base::subspan(i, n); }
70
71
template
<
size_t
i,
size_t
n = D>
72
[[nodiscard]]
constexpr
Span
<T, n !=
D
? n : (N !=
D
? N - i :
D
)>
subspan
()
const
noexcept
{
73
return
Base::template
subspan<i, n>
();
74
}
75
76
/// Get first `n` elements while keeping track of size statically - useful for structured binding!
77
template
<
size_t
n>
78
[[nodiscard]]
constexpr
Span<T, n>
span
() const noexcept {
79
return
Base::template
subspan<0, n>
();
80
}
81
///@}
82
83
/// @name rsubspan
84
/// Similar to Span::subspan but in *reverse*:
85
///@{
86
[[nodiscard]]
constexpr
Span<T, D>
rsubspan
(
size_t
i,
size_t
n =
D
)
const
noexcept
{
87
return
n !=
D
?
subspan
(size() - i - n, n) :
subspan
(0, size() - i);
88
}
89
90
/// `span.rsubspan(3, 5)` removes the last 3 elements and picks 5 elements starting before those.
91
template
<
size_t
i,
size_t
n = D>
92
[[nodiscard]]
constexpr
Span
<T, n !=
D
? n : (N !=
D
? N - i :
D
)>
rsubspan
()
const
noexcept
{
93
if
constexpr
(n !=
D
)
94
return
Span<T, n>
(data() + size() - i - n);
95
else
if
constexpr
(N !=
D
)
96
return
Span<T, N - i>
(data());
97
else
98
return
Span<T, D>
(data(), size() - i);
99
}
100
///@}
101
};
102
103
static_assert
(std::ranges::contiguous_range<Span<int>>);
104
105
template
<
class
T,
size_t
N = std::dynamic_extent>
106
using
View
=
Span<const T, N>
;
107
108
/// @name Deduction Guides
109
///@{
110
// clang-format off
111
template
<
class
I,
class
E>
Span
(I, E) ->
Span<std::remove_reference_t<std::iter_reference_t<I>
>>;
112
template
<
class
T,
size_t
N>
Span
(T (&)[N]) ->
Span< T, N>
;
113
template
<
class
T,
size_t
N>
Span
( std::array<T, N>&) ->
Span< T, N>
;
114
template
<
class
T,
size_t
N>
Span
(
const
std::array<T, N>&) ->
Span<const T, N>
;
115
template
<
class
R>
Span
(R&&) ->
Span<std::remove_reference_t<std::ranges::range_reference_t<R>
>>;
116
template
<Vectorlike Vec>
Span
( Vec&) ->
Span< typename Vec::value_type, std::dynamic_extent>
;
117
template
<Vectorlike Vec>
Span
(
const
Vec&) ->
Span<const typename Vec::value_type, std::dynamic_extent>
;
118
// clang-format on
119
///@}
120
121
template
<
size_t
I,
class
T,
size_t
N>
122
requires
(N != std::dynamic_extent)
constexpr
decltype
(
auto
)
get
(
Span<T, N>
span)
noexcept
{
123
static_assert
(I < N,
"index I out of bound N"
);
124
return
span[I];
125
}
126
127
}
// namespace fe
128
129
namespace
std
{
130
/// @name Structured Binding Support for Span
131
///@{
132
template
<
class
T,
size_t
N>
133
requires
(N != std::dynamic_extent)
struct
tuple_size<
fe::Span<T, N>
> :
std
::integral_constant<size_t, N> {};
134
135
template
<
size_t
I,
class
T,
size_t
N>
136
requires
(N != std::dynamic_extent)
struct
tuple_element<I,
fe::Span<T, N>
> {
137
using
type
=
typename
fe::Span<T, N>::reference
;
138
};
139
///@}
140
}
// namespace std
fe::Span
This is a thin wrapper for std::span<T, N> with the following additional features:
Definition
span.h:33
fe::Span::Span
constexpr Span(typename Base::pointer p) noexcept
Definition
span.h:57
fe::Span< const T, N >::span
constexpr Span< T, n > span() const noexcept
Definition
span.h:78
fe::Span::subspan
constexpr Span< T, D > subspan(size_t i, size_t n=D) const noexcept
Definition
span.h:69
fe::Span::Base
std::span< T, N > Base
Definition
span.h:35
fe::Span::Span
constexpr Span(std::span< T, N > span) noexcept
Definition
span.h:47
fe::Span::rsubspan
constexpr Span< T, n !=D ? n :(N !=D ? N - i :D)> rsubspan() const noexcept
span.rsubspan(3, 5) removes the last 3 elements and picks 5 elements starting before those.
Definition
span.h:92
fe::Span< const T, N >::D
static constexpr auto D
Definition
span.h:36
fe::Span::rsubspan
constexpr Span< T, D > rsubspan(size_t i, size_t n=D) const noexcept
Definition
span.h:86
fe::Span::subspan
constexpr Span< T, n !=D ? n :(N !=D ? N - i :D)> subspan() const noexcept
Definition
span.h:72
fe::Vectorlike
Something which behaves like std::vector or std::array.
Definition
span.h:13
fe
Definition
algo.h:17
fe::View
Span< const T, N > View
Definition
span.h:106
fe::get
constexpr decltype(auto) get(Span< T, N > span) noexcept
Definition
span.h:122
std
Definition
span.h:129
std::tuple_element< I, fe::Span< T, N > >::type
typename fe::Span< T, N >::reference type
Definition
span.h:137
fe
span.h
Generated by
1.18.0