5#ifndef DUNE_COMMON_STD_SPAN_HH
6#define DUNE_COMMON_STD_SPAN_HH
13#if __has_include(<span>)
19#if __has_include(<version>)
24#include <dune/common/std/memory.hh>
31#if __cpp_lib_span >= 202002L
39template <std::
size_t Extent>
43 using size_type = std::size_t;
46 constexpr SpanSize () =
default;
48 constexpr SpanSize ([[maybe_unused]] size_type
size)
noexcept
54 constexpr SpanSize ([[maybe_unused]] Iter first, [[maybe_unused]] Iter last)
noexcept
56 assert((std::distance(first,last) == Extent));
59 constexpr size_type
size ()
const noexcept {
return Extent; }
66 using size_type = std::size_t;
69 constexpr SpanSize (size_type
size = 0) noexcept
74 constexpr SpanSize (Iter first, Iter last) noexcept
75 : size_(std::distance(first,last))
78 constexpr size_type
size ()
const noexcept {
return size_; }
85struct TypeIdentity {
using type = T; };
88using TypeIdentity_t =
typename TypeIdentity<T>::type;
132template <
class Element, std::
size_t Extent = Std::dynamic_extent>
134 :
public Impl::SpanSize<Extent>
136 using base_type = Impl::SpanSize<Extent>;
138 static_assert(std::is_object_v<Element> && !std::is_abstract_v<Element>);
141 using element_type = Element;
142 using value_type = std::remove_cv_t<element_type>;
143 using size_type = std::size_t;
144 using difference_type = std::ptrdiff_t;
145 using pointer = element_type*;
146 using reference = element_type&;
147 using const_reference =
const element_type&;
148 using iterator = pointer;
149 using reverse_iterator = std::reverse_iterator<iterator>;
150#if __cpp_lib_ranges_as_const >202311L
151 using const_iterator = std::const_iterator<iterator>;
152 using const_reverse_iterator = std::const_iterator<reverse_iterator>;
154 using const_iterator =
const iterator;
155 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
159 static constexpr size_type extent = Extent;
166 template <std::size_t e = extent,
174 template <
class Iter,
175 class U = std::remove_reference_t<decltype(*std::declval<Iter>())>,
176 std::enable_if_t<std::is_convertible_v<U(*)[], element_type(*)[]>,
int> = 0>
177 #if __cpp_conditional_explicit >= 201806L
186 template <
class Iter,
187 class U = std::remove_reference_t<decltype(*std::declval<Iter>())>,
188 std::enable_if_t<std::is_convertible_v<U(*)[], element_type(*)[]>,
int> = 0>
189 #if __cpp_conditional_explicit >= 201806L
198 template <
class Range,
199 decltype(std::begin(std::declval<Range>()), std::end(std::declval<Range>()),
bool{}) =
true,
200 std::enable_if_t<not std::is_array_v<Range>,
int> = 0>
201 #
if __cpp_conditional_explicit >= 201806L
209 template <std::size_t N, std::size_t e = extent,
211 constexpr span (Impl::TypeIdentity_t<element_type> (&
data)[N])
noexcept
217 template <
class T,
size_t N, std::size_t e = extent,
219 std::enable_if_t<std::is_convertible_v<T(*)[], element_type(*)[]>,
int> = 0>
220 constexpr span (std::array<T, N>& arr) noexcept
226 template <
class T,
size_t N, std::size_t e = extent,
228 std::enable_if_t<std::is_convertible_v<
const T(*)[], element_type(*)[]>,
int> = 0>
229 constexpr span (
const std::array<T, N>& arr) noexcept
235 template <
class E = element_type,
236 std::enable_if_t<std::is_const_v<E>,
int> = 0>
237 #if __cpp_conditional_explicit >= 201806L
240 constexpr span (std::initializer_list<value_type> il)
241 : base_type(il.size())
246 constexpr span (
const span& other)
noexcept =
default;
249 template <
class OtherElementType, std::size_t OtherExtent,
251 std::enable_if_t<std::is_convertible_v<OtherElementType(*)[], element_type(*)[]>,
int> = 0>
252 #if __cpp_conditional_explicit >= 201806L
256 : base_type(s.size())
270 constexpr iterator
begin () const noexcept {
return data_; }
273 constexpr iterator
end () const noexcept {
return data_ + size(); }
276 constexpr const_iterator
cbegin () const noexcept {
return data_; }
279 constexpr const_iterator
cend () const noexcept {
return data_ + size(); }
282 constexpr reverse_iterator
rbegin() const noexcept {
return reverse_iterator{
end()}; }
285 constexpr reverse_iterator
rend() const noexcept {
return reverse_iterator{
begin()}; }
288 constexpr const_reverse_iterator
crbegin() const noexcept {
return reverse_iterator{
end()}; }
291 constexpr const_reverse_iterator
crend() const noexcept {
return reverse_iterator{
begin()}; }
302 assert(not
empty() &&
"front of empty span does not exist");
307 constexpr reference
back ()
const
309 assert(not
empty() &&
"front of empty span does not exist");
310 return data_[size()-1];
314 constexpr reference
at (size_type i)
const
317 throw std::out_of_range(
"Index " + std::to_string(i) +
" out of range.");
322 constexpr reference
operator[] (size_type i)
const {
return data_[i]; }
325 constexpr pointer
data () const noexcept {
return data_; }
334 template <std::
size_t Count>
337 static_assert(Count <= Extent);
338 assert(Count <= size());
343 template <std::
size_t Count>
346 static_assert(Count <= Extent);
347 assert(Count <= size());
353 static constexpr std::size_t subspan_extent (std::size_t O, std::size_t C)
noexcept
366 template <std::
size_t Offset, std::
size_t Count = Std::dynamic_extent>
367 constexpr span<element_type, subspan_extent(Offset,Count)>
subspan ()
const
369 static_assert(Offset <= Extent && (Count ==
Std::dynamic_extent || Count <= Extent - Offset));
371 return span<element_type, subspan_extent(Offset,Count)>{
378 assert(count <= size());
385 assert(count <= size());
408 using base_type::size;
411 constexpr size_type
size_bytes () const noexcept {
return size() *
sizeof(element_type); }
414 [[nodiscard]]
constexpr bool empty () const noexcept {
return size() == 0; }
425template <
class T, std::
size_t N>
429template <
class ElementType,
class I, std::size_t Extent,
430 std::enable_if_t<std::is_convertible_v<I,std::size_t>,
int> = 0>
431span (ElementType*, std::integral_constant<I,Extent>)
432 -> span<ElementType, Extent>;
434template <
class ElementType,
class I,
435 std::enable_if_t<std::is_integral_v<I>,
int> = 0,
436 std::enable_if_t<std::is_convertible_v<I,std::size_t>,
int> = 0>
437span (ElementType*, I)
438 -> span<ElementType, Std::dynamic_extent>;
441 class Element = std::remove_reference_t<decltype(*std::declval<Iter>())>>
443 -> span<Element, Std::dynamic_extent>;
445template <
class Range,
446 class First =
decltype(std::begin(std::declval<Range>())),
447 class Last =
decltype(std::end(std::declval<Range>())),
448 class Element = std::remove_reference_t<
decltype(*std::declval<First>())>>
450 -> span<Element, Std::dynamic_extent>;
452template <
class T,
size_t N>
453span (std::array<T, N>&) -> span<T, N>;
455template <
class T,
size_t N>
456span (
const std::array<T, N>&) -> span<const T, N>;
A contiguous sequence of elements with static or dynamic extent.
Definition: span.hh:135
constexpr reference front() const
Access the first element.
Definition: span.hh:300
constexpr span(const span &other) noexcept=default
Copy constructor.
constexpr iterator begin() const noexcept
Returns an iterator to the beginning.
Definition: span.hh:270
constexpr const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition: span.hh:276
constexpr span(std::array< T, N > &arr) noexcept
Constructs a span that is a view over the array.
Definition: span.hh:220
constexpr iterator end() const noexcept
Returns an iterator to the end.
Definition: span.hh:273
constexpr span< element_type, Std::dynamic_extent > subspan(size_type offset, size_type count=Std::dynamic_extent) const
Obtains a subspan consisting of count elements of the sequence starting at offset.
Definition: span.hh:394
constexpr span & operator=(const span &other) noexcept=default
Copy assignment operator.
constexpr reference at(size_type i) const
Access specified element with bounds checking.
Definition: span.hh:314
constexpr span< element_type, Std::dynamic_extent > first(size_type count) const
Obtains a subspan consisting of the first count elements of the sequence.
Definition: span.hh:376
constexpr span< element_type, subspan_extent(Offset, Count)> subspan() const
Obtains a subspan consisting of Count elements of the sequence starting at Offset.
Definition: span.hh:367
constexpr const_reverse_iterator crend() const noexcept
Returns a reverse iterator ending at the beginning.
Definition: span.hh:291
constexpr reverse_iterator rend() const noexcept
Returns a reverse iterator ending at the beginning.
Definition: span.hh:285
constexpr pointer data() const noexcept
Direct access to the underlying contiguous storage.
Definition: span.hh:325
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hh:411
constexpr const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator starting at the end.
Definition: span.hh:288
constexpr bool empty() const noexcept
Checks if the sequence is empty.
Definition: span.hh:414
constexpr span< element_type, Count > last() const
Obtains a subspan consisting of the last Count elements of the sequence.
Definition: span.hh:344
constexpr span(Range &range)
Constructs a span that is a view over the range [range.begin(), range.end())
Definition: span.hh:204
constexpr reverse_iterator rbegin() const noexcept
Returns a reverse iterator starting at the end.
Definition: span.hh:282
constexpr span< element_type, Std::dynamic_extent > last(size_type count) const
Obtains a subspan consisting of the last count elements of the sequence.
Definition: span.hh:383
constexpr const_iterator cend() const noexcept
Returns an iterator to the end.
Definition: span.hh:279
constexpr span< element_type, Count > first() const
Obtains a subspan consisting of the first Count elements of the sequence.
Definition: span.hh:335
constexpr reference back() const
Access the last element.
Definition: span.hh:307
constexpr span(const std::array< T, N > &arr) noexcept
Constructs a span that is a view over the const array.
Definition: span.hh:229
constexpr reference operator[](size_type i) const
Access specified element.
Definition: span.hh:322
A few common exception classes.
static constexpr IntegralRange< std::decay_t< T > > range(T &&from, U &&to) noexcept
free standing function for setting up a range based for loop over an integer range for (auto i: range...
Definition: rangeutilities.hh:288
Namespace for features backported from new C++ standards.
Definition: algorithm.hh:19
constexpr auto to_address(T &&p) noexcept
Obtain the address represented by p without forming a reference to the object pointed to by p.
Definition: memory.hh:47
constexpr std::size_t dynamic_extent
A constant of type std::size_t that is used to differentiate std::span of static and dynamic extent.
Definition: span.hh:29
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75