5#ifndef DUNE_COMMON_STD_SPAN_HH
6#define DUNE_COMMON_STD_SPAN_HH
16#if __has_include(<version>)
21#include <dune/common/std/memory.hh>
30template <std::
size_t Extent>
34 using size_type = std::size_t;
37 constexpr SpanSize () =
default;
39 constexpr SpanSize ([[maybe_unused]] size_type
size)
noexcept
45 constexpr SpanSize ([[maybe_unused]] Iter first, [[maybe_unused]] Iter last)
noexcept
47 assert((std::distance(first,last) == Extent));
50 constexpr size_type
size () const noexcept {
return Extent; }
57 using size_type = std::size_t;
60 constexpr SpanSize (size_type
size = 0) noexcept
65 constexpr SpanSize (Iter first, Iter last) noexcept
66 : size_(std::distance(first,last))
69 constexpr size_type
size () const noexcept {
return size_; }
76struct TypeIdentity {
using type = T; };
79using TypeIdentity_t =
typename TypeIdentity<T>::type;
123template <
class Element, std::
size_t Extent = Std::dynamic_extent>
125 :
public Impl::SpanSize<Extent>
127 using base_type = Impl::SpanSize<Extent>;
129 static_assert(std::is_object_v<Element> && !std::is_abstract_v<Element>);
132 using element_type = Element;
133 using value_type = std::remove_cv_t<element_type>;
134 using size_type = std::size_t;
135 using difference_type = std::ptrdiff_t;
136 using pointer = element_type*;
137 using reference = element_type&;
138 using const_reference =
const element_type&;
139 using iterator = pointer;
140 using reverse_iterator = std::reverse_iterator<iterator>;
141#if __cpp_lib_ranges_as_const >202311L
142 using const_iterator = std::const_iterator<iterator>;
143 using const_reverse_iterator = std::const_iterator<reverse_iterator>;
145 using const_iterator =
const iterator;
146 using const_reverse_iterator = std::reverse_iterator<const_iterator>;
150 static constexpr size_type extent = Extent;
157 template <std::size_t e = extent,
165 template <
class Iter,
166 class U = std::remove_reference_t<decltype(*std::declval<Iter>())>,
167 std::enable_if_t<std::is_convertible_v<U(*)[], element_type(*)[]>,
int> = 0>
168 #if __cpp_conditional_explicit >= 201806L
177 template <
class Iter,
178 class U = std::remove_reference_t<decltype(*std::declval<Iter>())>,
179 std::enable_if_t<std::is_convertible_v<U(*)[], element_type(*)[]>,
int> = 0>
180 #if __cpp_conditional_explicit >= 201806L
189 template <
class Range,
190 decltype(std::begin(std::declval<Range>()), std::end(std::declval<Range>()),
bool{}) =
true,
191 std::enable_if_t<not std::is_array_v<Range>,
int> = 0>
192 #
if __cpp_conditional_explicit >= 201806L
200 template <std::size_t N, std::size_t e = extent,
202 constexpr span (Impl::TypeIdentity_t<element_type> (&
data)[N])
noexcept
208 template <
class T,
size_t N, std::size_t e = extent,
210 std::enable_if_t<std::is_convertible_v<T(*)[], element_type(*)[]>,
int> = 0>
211 constexpr span (std::array<T, N>& arr) noexcept
217 template <
class T,
size_t N, std::size_t e = extent,
219 std::enable_if_t<std::is_convertible_v<
const T(*)[], element_type(*)[]>,
int> = 0>
220 constexpr span (
const std::array<T, N>& arr) noexcept
226 template <
class E = element_type,
227 std::enable_if_t<std::is_const_v<E>,
int> = 0>
228 #if __cpp_conditional_explicit >= 201806L
231 constexpr span (std::initializer_list<value_type> il)
232 : base_type(il.size())
237 constexpr span (
const span& other)
noexcept =
default;
240 template <
class OtherElementType, std::size_t OtherExtent,
242 std::enable_if_t<std::is_convertible_v<OtherElementType(*)[], element_type(*)[]>,
int> = 0>
243 #if __cpp_conditional_explicit >= 201806L
247 : base_type(s.size())
261 constexpr iterator
begin () const noexcept {
return data_; }
264 constexpr iterator
end () const noexcept {
return data_ + size(); }
267 constexpr const_iterator
cbegin () const noexcept {
return data_; }
270 constexpr const_iterator
cend () const noexcept {
return data_ + size(); }
273 constexpr reverse_iterator
rbegin() const noexcept {
return reverse_iterator{
end()}; }
276 constexpr reverse_iterator
rend() const noexcept {
return reverse_iterator{
begin()}; }
279 constexpr const_reverse_iterator
crbegin() const noexcept {
return reverse_iterator{
end()}; }
282 constexpr const_reverse_iterator
crend() const noexcept {
return reverse_iterator{
begin()}; }
293 assert(not
empty() &&
"front of empty span does not exist");
298 constexpr reference
back ()
const
300 assert(not
empty() &&
"front of empty span does not exist");
301 return data_[size()-1];
305 constexpr reference
at (size_type i)
const
308 throw std::out_of_range(
"Index " + std::to_string(i) +
" out of range.");
313 constexpr reference
operator[] (size_type i)
const {
return data_[i]; }
316 constexpr pointer
data () const noexcept {
return data_; }
325 template <std::
size_t Count>
328 static_assert(Count <= Extent);
329 assert(Count <= size());
334 template <std::
size_t Count>
337 static_assert(Count <= Extent);
338 assert(Count <= size());
344 static constexpr std::size_t subspan_extent (std::size_t O, std::size_t C)
noexcept
357 template <std::
size_t Offset, std::
size_t Count = Std::dynamic_extent>
358 constexpr span<element_type, subspan_extent(Offset,Count)>
subspan ()
const
360 static_assert(Offset <= Extent && (Count ==
Std::dynamic_extent || Count <= Extent - Offset));
362 return span<element_type, subspan_extent(Offset,Count)>{
369 assert(count <= size());
376 assert(count <= size());
399 using base_type::size;
402 constexpr size_type
size_bytes () const noexcept {
return size() *
sizeof(element_type); }
405 [[nodiscard]]
constexpr bool empty () const noexcept {
return size() == 0; }
416template <
class T, std::
size_t N>
420template <
class ElementType,
class I, std::size_t Extent,
421 std::enable_if_t<std::is_convertible_v<I,std::size_t>,
int> = 0>
422span (ElementType*, std::integral_constant<I,Extent>)
423 -> span<ElementType, Extent>;
425template <
class ElementType,
class I,
426 std::enable_if_t<std::is_integral_v<I>,
int> = 0,
427 std::enable_if_t<std::is_convertible_v<I,std::size_t>,
int> = 0>
428span (ElementType*, I)
429 -> span<ElementType, Std::dynamic_extent>;
432 class Element = std::remove_reference_t<decltype(*std::declval<Iter>())>>
434 -> span<Element, Std::dynamic_extent>;
436template <
class Range,
437 class First =
decltype(std::begin(std::declval<Range>())),
438 class Last =
decltype(std::end(std::declval<Range>())),
439 class Element = std::remove_reference_t<
decltype(*std::declval<First>())>>
441 -> span<Element, Std::dynamic_extent>;
443template <
class T,
size_t N>
444span (std::array<T, N>&) -> span<T, N>;
446template <
class T,
size_t N>
447span (
const std::array<T, N>&) -> span<const T, N>;
A contiguous sequence of elements with static or dynamic extent.
Definition: span.hh:126
constexpr reference front() const
Access the first element.
Definition: span.hh:291
constexpr span(const span &other) noexcept=default
Copy constructor.
constexpr iterator begin() const noexcept
Returns an iterator to the beginning.
Definition: span.hh:261
constexpr const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition: span.hh:267
constexpr span(std::array< T, N > &arr) noexcept
Constructs a span that is a view over the array.
Definition: span.hh:211
constexpr iterator end() const noexcept
Returns an iterator to the end.
Definition: span.hh:264
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:385
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:305
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:367
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:358
constexpr const_reverse_iterator crend() const noexcept
Returns a reverse iterator ending at the beginning.
Definition: span.hh:282
constexpr reverse_iterator rend() const noexcept
Returns a reverse iterator ending at the beginning.
Definition: span.hh:276
constexpr pointer data() const noexcept
Direct access to the underlying contiguous storage.
Definition: span.hh:316
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition: span.hh:402
constexpr const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator starting at the end.
Definition: span.hh:279
constexpr bool empty() const noexcept
Checks if the sequence is empty.
Definition: span.hh:405
constexpr span< element_type, Count > last() const
Obtains a subspan consisting of the last Count elements of the sequence.
Definition: span.hh:335
constexpr span(Range &range)
Constructs a span that is a view over the range [range.begin(), range.end())
Definition: span.hh:195
constexpr reverse_iterator rbegin() const noexcept
Returns a reverse iterator starting at the end.
Definition: span.hh:273
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:374
constexpr const_iterator cend() const noexcept
Returns an iterator to the end.
Definition: span.hh:270
constexpr span< element_type, Count > first() const
Obtains a subspan consisting of the first Count elements of the sequence.
Definition: span.hh:326
constexpr reference back() const
Access the last element.
Definition: span.hh:298
constexpr span(const std::array< T, N > &arr) noexcept
Constructs a span that is a view over the const array.
Definition: span.hh:220
constexpr reference operator[](size_type i) const
Access specified element.
Definition: span.hh:313
A few common exception classes.
constexpr auto max
Function object that returns the greater of the given values.
Definition: hybridutilities.hh:484
Namespace for features backported from new C++ standards.
Definition: default_accessor.hh:10
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:26
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