Loading...
Searching...
No Matches
span.hh
Go to the documentation of this file.
// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
// vi: set et ts=4 sw=2 sts=2:
// SPDX-FileCopyrightInfo: Copyright © DUNE Project contributors, see file LICENSE.md in module root
// SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
#ifndef DUNE_COMMON_STD_SPAN_HH
#define DUNE_COMMON_STD_SPAN_HH
#include <cassert>
#include <cstddef>
#include <exception>
#include <iterator>
#include <limits>
#if __has_include(<span>)
#include <span>
#endif
#include <stdexcept>
#include <string>
#include <type_traits>
#if __has_include(<version>)
#include <version>
#endif
#include <dune/common/exceptions.hh>
#include <dune/common/std/memory.hh>
namespace Dune::Std {
inline constexpr std::size_t dynamic_extent = std::dynamic_extent;
#if __cpp_lib_span >= 202002L
using std::span;
#else
namespace Impl {
template <std::size_t Extent>
class SpanSize
{
public:
using size_type = std::size_t;
public:
constexpr SpanSize () = default;
constexpr SpanSize ([[maybe_unused]] size_type size) noexcept
{
assert(Extent == Std::dynamic_extent || Extent == size);
}
template <class Iter>
constexpr SpanSize ([[maybe_unused]] Iter first, [[maybe_unused]] Iter last) noexcept
{
assert((std::distance(first,last) == Extent));
}
constexpr size_type size () const noexcept { return Extent; }
};
template <>
class SpanSize<Std::dynamic_extent>
{
public:
using size_type = std::size_t;
public:
constexpr SpanSize (size_type size = 0) noexcept
: size_(size)
{}
template <class Iter>
constexpr SpanSize (Iter first, Iter last) noexcept
: size_(std::distance(first,last))
{}
constexpr size_type size () const noexcept { return size_; }
private:
size_type size_;
};
template <class T>
struct TypeIdentity { using type = T; };
template <class T>
using TypeIdentity_t = typename TypeIdentity<T>::type;
} // end namespace Impl
template <class Element, std::size_t Extent = Std::dynamic_extent>
class span
: public Impl::SpanSize<Extent>
{
using base_type = Impl::SpanSize<Extent>; // base_type implements the member variable size()
static_assert(std::is_object_v<Element> && !std::is_abstract_v<Element>);
public:
using element_type = Element;
using value_type = std::remove_cv_t<element_type>;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using pointer = element_type*;
using reference = element_type&;
using const_reference = const element_type&;
using iterator = pointer;
using reverse_iterator = std::reverse_iterator<iterator>;
#if __cpp_lib_ranges_as_const >202311L
using const_iterator = std::const_iterator<iterator>;
using const_reverse_iterator = std::const_iterator<reverse_iterator>;
#else
using const_iterator = const iterator;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
#endif
static constexpr size_type extent = Extent;
public:
template <std::size_t e = extent,
std::enable_if_t<(e == dynamic_extent || e == 0), int> = 0>
constexpr span () noexcept
: base_type{}
, data_{}
{}
template <class Iter,
class U = std::remove_reference_t<decltype(*std::declval<Iter>())>,
std::enable_if_t<std::is_convertible_v<U(*)[], element_type(*)[]>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(extent != Std::dynamic_extent)
#endif
constexpr span (Iter first, size_type size)
: base_type(size)
, data_(Std::to_address(first))
{}
template <class Iter,
class U = std::remove_reference_t<decltype(*std::declval<Iter>())>,
std::enable_if_t<std::is_convertible_v<U(*)[], element_type(*)[]>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(extent != Std::dynamic_extent)
#endif
constexpr span (Iter first, Iter last)
: base_type(first,last)
, data_(Std::to_address(first))
{}
template <class Range,
decltype(std::begin(std::declval<Range>()), std::end(std::declval<Range>()), bool{}) = true,
std::enable_if_t<not std::is_array_v<Range>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(extent != Std::dynamic_extent)
#endif
constexpr span (Range& range)
: span(std::begin(range), std::end(range))
{}
template <std::size_t N, std::size_t e = extent,
std::enable_if_t<(e == Std::dynamic_extent || e == N), int> = 0>
constexpr span (Impl::TypeIdentity_t<element_type> (&data)[N]) noexcept
: base_type(N)
, data_(data)
{}
template <class T, size_t N, std::size_t e = extent,
std::enable_if_t<(e == Std::dynamic_extent || e == N), int> = 0,
std::enable_if_t<std::is_convertible_v<T(*)[], element_type(*)[]>, int> = 0>
constexpr span (std::array<T, N>& arr) noexcept
: base_type(N)
, data_(arr.data())
{}
template <class T, size_t N, std::size_t e = extent,
std::enable_if_t<(e == Std::dynamic_extent || e == N), int> = 0,
std::enable_if_t<std::is_convertible_v<const T(*)[], element_type(*)[]>, int> = 0>
constexpr span (const std::array<T, N>& arr) noexcept
: base_type(N)
, data_(arr.data())
{}
template <class E = element_type,
std::enable_if_t<std::is_const_v<E>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(extent != Std::dynamic_extent)
#endif
constexpr span (std::initializer_list<value_type> il)
: base_type(il.size())
, data_(il.begin())
{}
constexpr span (const span& other) noexcept = default;
template <class OtherElementType, std::size_t OtherExtent,
std::enable_if_t<(extent == Std::dynamic_extent || OtherExtent == Std::dynamic_extent || extent == OtherExtent), int> = 0,
std::enable_if_t<std::is_convertible_v<OtherElementType(*)[], element_type(*)[]>, int> = 0>
#if __cpp_conditional_explicit >= 201806L
explicit(extent != Std::dynamic_extent && OtherExtent == Std::dynamic_extent)
#endif
constexpr span (const span<OtherElementType, OtherExtent>& s) noexcept
: base_type(s.size())
, data_(s.data())
{}
constexpr span& operator= (const span& other) noexcept = default;
constexpr iterator begin () const noexcept { return data_; }
constexpr iterator end () const noexcept { return data_ + size(); }
constexpr const_iterator cbegin () const noexcept { return data_; }
constexpr const_iterator cend () const noexcept { return data_ + size(); }
constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
constexpr const_reverse_iterator crbegin() const noexcept { return reverse_iterator{end()}; }
constexpr const_reverse_iterator crend() const noexcept { return reverse_iterator{begin()}; }
constexpr reference front () const
{
assert(not empty() && "front of empty span does not exist");
return data_[0];
}
constexpr reference back () const
{
assert(not empty() && "front of empty span does not exist");
return data_[size()-1];
}
constexpr reference at (size_type i) const
{
if (i >= size())
throw std::out_of_range("Index " + std::to_string(i) + " out of range.");
return data_[i];
}
constexpr reference operator[] (size_type i) const { return data_[i]; }
constexpr pointer data () const noexcept { return data_; }
template <std::size_t Count>
constexpr span<element_type, Count> first () const
{
static_assert(Count <= Extent);
assert(Count <= size());
return span<element_type, Count>{data(), Count};
}
template <std::size_t Count>
constexpr span<element_type, Count> last () const
{
static_assert(Count <= Extent);
assert(Count <= size());
return span<element_type, Count>{data()+ (size() - Count), Count};
}
private:
static constexpr std::size_t subspan_extent (std::size_t O, std::size_t C) noexcept
{
return (C != Std::dynamic_extent) ? C :
(Extent != Std::dynamic_extent) ? Extent - O : Std::dynamic_extent;
}
public:
template <std::size_t Offset, std::size_t Count = Std::dynamic_extent>
constexpr span<element_type, subspan_extent(Offset,Count)> subspan () const
{
static_assert(Offset <= Extent && (Count == Std::dynamic_extent || Count <= Extent - Offset));
assert(Offset <= size() && (Count == Std::dynamic_extent || Count <= size() - Offset));
return span<element_type, subspan_extent(Offset,Count)>{
data() + Offset, Count != Std::dynamic_extent ? Count : size() - Offset};
}
constexpr span<element_type, Std::dynamic_extent> first (size_type count) const
{
assert(count <= size());
return span<element_type, Std::dynamic_extent>{data(), count};
}
constexpr span<element_type, Std::dynamic_extent> last (size_type count) const
{
assert(count <= size());
return span<element_type, Std::dynamic_extent>{data()+ (size() - count), count};
}
constexpr span<element_type, Std::dynamic_extent> subspan (size_type offset, size_type count = Std::dynamic_extent) const
{
assert(offset <= size() && (count == Std::dynamic_extent || count <= size() - offset));
return span<element_type, Std::dynamic_extent>{
data() + offset, count == Std::dynamic_extent ? size() - offset : count};
}
using base_type::size;
constexpr size_type size_bytes () const noexcept { return size() * sizeof(element_type); }
[[nodiscard]] constexpr bool empty () const noexcept { return size() == 0; }
private:
pointer data_;
};
// deduction guide
// @{
template <class T, std::size_t N>
span (T (&)[N])
-> span<T, N>;
template <class ElementType, class I, std::size_t Extent,
std::enable_if_t<std::is_convertible_v<I,std::size_t>, int> = 0>
span (ElementType*, std::integral_constant<I,Extent>)
-> span<ElementType, Extent>;
template <class ElementType, class I,
std::enable_if_t<std::is_integral_v<I>, int> = 0,
std::enable_if_t<std::is_convertible_v<I,std::size_t>, int> = 0>
span (ElementType*, I)
-> span<ElementType, Std::dynamic_extent>;
template <class Iter,
class Element = std::remove_reference_t<decltype(*std::declval<Iter>())>>
span (Iter,Iter)
-> span<Element, Std::dynamic_extent>;
template <class Range,
class First = decltype(std::begin(std::declval<Range>())),
class Last = decltype(std::end(std::declval<Range>())),
class Element = std::remove_reference_t<decltype(*std::declval<First>())>>
span (Range&)
-> span<Element, Std::dynamic_extent>;
template <class T, size_t N>
span (std::array<T, N>&) -> span<T, N>;
template <class T, size_t N>
span (const std::array<T, N>&) -> span<const T, N>;
// @}
#endif // __cpp_lib_span
} // end namespace Dune::Std
#endif // DUNE_COMMON_STD_SPAN_HH
exceptions.hh
A few common exception classes.
memory.hh
Dune::range
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
std
STL namespace.
Dune::size
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
Dune::Std
Namespace for features backported from new C++ standards.
Definition algorithm.hh:19
Dune::Std::span
span(T(&)[N]) -> span< T, N >
Dune::Std::to_address
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
Dune::Std::dynamic_extent
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
Dune::Std::span
A contiguous sequence of elements with static or dynamic extent.
Definition span.hh:135
Dune::Std::span::difference_type
std::ptrdiff_t difference_type
Definition span.hh:144
Dune::Std::span::const_reference
const element_type & const_reference
Definition span.hh:147
Dune::Std::span::front
constexpr reference front() const
Access the first element.
Definition span.hh:300
Dune::Std::span::reference
element_type & reference
Definition span.hh:146
Dune::Std::span::span
constexpr span(const span &other) noexcept=default
Copy constructor.
Dune::Std::span::iterator
pointer iterator
Definition span.hh:148
Dune::Std::span::extent
static constexpr size_type extent
Definition span.hh:159
Dune::Std::span::begin
constexpr iterator begin() const noexcept
Returns an iterator to the beginning.
Definition span.hh:270
Dune::Std::span::cbegin
constexpr const_iterator cbegin() const noexcept
Returns an iterator to the beginning.
Definition span.hh:276
Dune::Std::span::span
constexpr span(std::array< T, N > &arr) noexcept
Constructs a span that is a view over the array.
Definition span.hh:220
Dune::Std::span::reverse_iterator
std::reverse_iterator< iterator > reverse_iterator
Definition span.hh:149
Dune::Std::span::end
constexpr iterator end() const noexcept
Returns an iterator to the end.
Definition span.hh:273
Dune::Std::span::subspan
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
Dune::Std::span::span
constexpr span() noexcept
Default construct an empty span.
Definition span.hh:168
Dune::Std::span::operator=
constexpr span & operator=(const span &other) noexcept=default
Copy assignment operator.
Dune::Std::span::size_type
std::size_t size_type
Definition span.hh:143
Dune::Std::span::pointer
element_type * pointer
Definition span.hh:145
Dune::Std::span::at
constexpr reference at(size_type i) const
Access specified element with bounds checking.
Definition span.hh:314
Dune::Std::span::value_type
std::remove_cv_t< element_type > value_type
Definition span.hh:142
Dune::Std::span::first
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
Dune::Std::span::subspan
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
Dune::Std::span::const_iterator
const iterator const_iterator
Definition span.hh:154
Dune::Std::span::crend
constexpr const_reverse_iterator crend() const noexcept
Returns a reverse iterator ending at the beginning.
Definition span.hh:291
Dune::Std::span::rend
constexpr reverse_iterator rend() const noexcept
Returns a reverse iterator ending at the beginning.
Definition span.hh:285
Dune::Std::span::data
constexpr pointer data() const noexcept
Direct access to the underlying contiguous storage.
Definition span.hh:325
Dune::Std::span::size_bytes
constexpr size_type size_bytes() const noexcept
Returns the size of the sequence in bytes.
Definition span.hh:411
Dune::Std::span::crbegin
constexpr const_reverse_iterator crbegin() const noexcept
Returns a reverse iterator starting at the end.
Definition span.hh:288
Dune::Std::span::element_type
Element element_type
Definition span.hh:141
Dune::Std::span::empty
constexpr bool empty() const noexcept
Checks if the sequence is empty.
Definition span.hh:414
Dune::Std::span::last
constexpr span< element_type, Count > last() const
Obtains a subspan consisting of the last Count elements of the sequence.
Definition span.hh:344
Dune::Std::span::span
constexpr span(Range &range)
Constructs a span that is a view over the range [range.begin(), range.end()).
Definition span.hh:204
Dune::Std::span::rbegin
constexpr reverse_iterator rbegin() const noexcept
Returns a reverse iterator starting at the end.
Definition span.hh:282
Dune::Std::span::last
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
Dune::Std::span::const_reverse_iterator
std::reverse_iterator< const_iterator > const_reverse_iterator
Definition span.hh:155
Dune::Std::span::span
constexpr span(Impl::TypeIdentity_t< element_type >(&data)[N]) noexcept
Constructs a span that is a view over the C-array.
Definition span.hh:211
Dune::Std::span::cend
constexpr const_iterator cend() const noexcept
Returns an iterator to the end.
Definition span.hh:279
Dune::Std::span::first
constexpr span< element_type, Count > first() const
Obtains a subspan consisting of the first Count elements of the sequence.
Definition span.hh:335
Dune::Std::span::back
constexpr reference back() const
Access the last element.
Definition span.hh:307
Dune::Std::span::span
constexpr span(const std::array< T, N > &arr) noexcept
Constructs a span that is a view over the const array.
Definition span.hh:229
Dune::Std::span::operator[]
constexpr reference operator[](size_type i) const
Access specified element.
Definition span.hh:322
Dune::type