14 #ifndef RANGES_V3_VIEW_SPAN_HPP
15 #define RANGES_V3_VIEW_SPAN_HPP
32 #include <range/v3/detail/prologue.hpp>
42 using span_index_t = std::ptrdiff_t;
46 constexpr detail::span_index_t dynamic_extent = -1;
51 template(
typename To,
typename From)(
52 requires integral<To> AND integral<From>)
53 constexpr To narrow_cast(From from) noexcept
55 using C = common_type_t<To, From>;
56 return RANGES_EXPECT((from > 0) == (
static_cast<To
>(from) > 0)),
57 RANGES_EXPECT(
static_cast<C
>(from) ==
58 static_cast<C
>(
static_cast<To
>(from))),
59 static_cast<To
>(from);
63 constexpr span_index_t byte_size(span_index_t n) noexcept
65 return n == dynamic_extent ? dynamic_extent
66 : (RANGES_EXPECT(n >= 0),
67 RANGES_EXPECT(narrow_cast<std::size_t>(n) <=
68 PTRDIFF_MAX /
sizeof(T)),
69 n * narrow_cast<span_index_t>(
sizeof(T)));
72 template<span_index_t N>
77 constexpr span_extent() noexcept = default;
78 constexpr span_extent(span_index_t
size) noexcept
81 : span_extent{(RANGES_EXPECT(
size == N), tag{})}
84 constexpr span_index_t
size() const noexcept
92 constexpr span_extent(tag) noexcept
96 struct span_extent<dynamic_extent>
98 span_extent() =
default;
99 constexpr span_extent(span_index_t
size) noexcept
100 : size_{((void)RANGES_EXPECT(
size >= 0),
size)}
102 constexpr span_index_t
size() const noexcept
108 span_index_t size_ = 0;
111 constexpr span_index_t subspan_extent(span_index_t Extent, span_index_t Offset,
112 span_index_t Count) noexcept
114 return Count == dynamic_extent && Extent != dynamic_extent ? Extent - Offset
122 template(
typename Rng,
typename T)(
123 concept (span_compatible_range_)(Rng, T),
124 detail::is_convertible<detail::element_t<Rng>(*)[], T(*)[]>::value
128 template<
typename Rng,
typename T>
129 CPP_concept span_compatible_range =
130 sized_range<Rng> && contiguous_range<Rng> &&
131 CPP_concept_ref(ranges::span_compatible_range_, Rng, T);
135 template<
typename Rng, detail::span_index_t N>
136 CPP_concept span_dynamic_conversion =
137 N == dynamic_extent ||
138 range_cardinality<Rng>::value < cardinality();
142 template<
typename Rng, detail::span_index_t N>
143 CPP_concept span_static_conversion =
144 N != dynamic_extent && range_cardinality<Rng>::value == N;
148 template<
typename T, detail::span_index_t N = dynamic_extent>
151 span<T, N>, (N == dynamic_extent ? finite : static_cast<cardinality>(N))>
152 ,
public detail::span_extent<N>
154 CPP_assert(std::is_object<T>::value);
156 using element_type = T;
158 using index_type = detail::span_index_t;
159 using difference_type = index_type;
161 using reference = T &;
162 using iterator = T *;
165 static constexpr index_type extent = N;
167 constexpr
span() noexcept =
default;
168 constexpr
span(pointer ptr, index_type cnt) noexcept
169 : detail::span_extent<N>{(RANGES_EXPECT(cnt >= 0), cnt)}
170 , data_{(RANGES_EXPECT(0 == cnt || ptr !=
nullptr), ptr)}
172 template<
typename =
void>
174 constexpr
span(pointer
first, pointer last) noexcept
178 template(
typename Rng)(
179 requires (!same_as<
span, uncvref_t<Rng>>) AND
180 span_compatible_range<Rng, T> AND
181 span_dynamic_conversion<Rng, N>)
182 constexpr
span(Rng && rng) noexcept(noexcept(ranges::data(rng),
184 :
span{ranges::data(rng), detail::narrow_cast<index_type>(
ranges::size(rng))}
187 template(
typename Rng)(
188 requires (!same_as<
span, uncvref_t<Rng>>) AND
189 span_compatible_range<Rng, T> AND
190 span_static_conversion<Rng, N>)
191 constexpr
span(Rng && rng) noexcept(noexcept(ranges::data(rng)))
192 :
span{ranges::data(rng), N}
195 template<index_type Count>
198 static_assert(Count >= 0,
"Count of elements to extract cannot be negative.");
200 N == dynamic_extent || Count <= N,
201 "Count of elements to extract must be less than the static span extent.");
202 return RANGES_EXPECT(Count <=
size()),
203 RANGES_EXPECT(Count == 0 || data_ !=
nullptr),
208 return RANGES_EXPECT(cnt >= 0 && cnt <=
size()),
209 RANGES_EXPECT(cnt == 0 || data_ !=
nullptr),
span<T>{data_, cnt};
212 template<index_type Count>
215 static_assert(Count >= 0,
"Count of elements to extract cannot be negative.");
217 N == dynamic_extent || Count <= N,
218 "Count of elements to extract must be less than the static span extent.");
219 return RANGES_EXPECT(Count <=
size()),
220 RANGES_EXPECT((Count == 0 &&
size() == 0) || data_ !=
nullptr),
223 constexpr
span<T> last(index_type cnt)
const noexcept
225 return RANGES_EXPECT(cnt >= 0 && cnt <=
size()),
226 RANGES_EXPECT((cnt == 0 &&
size() == 0) || data_ !=
nullptr),
230 template<index_type Offset, index_type Count>
231 constexpr
span<T, detail::subspan_extent(N, Offset, Count)> subspan()
const
234 static_assert(Offset >= 0,
235 "Offset of first element to extract cannot be negative.");
236 static_assert(Count >= dynamic_extent,
237 "Count of elements to extract cannot be negative.");
239 N == dynamic_extent ||
240 N >= Offset + (Count == dynamic_extent ? 0 : Count),
241 "Sequence of elements to extract must be within the static span extent.");
242 return RANGES_EXPECT(
size() >=
243 Offset + (Count == dynamic_extent ? 0 : Count)),
244 RANGES_EXPECT((Offset == 0 && Count <= 0) || data_ !=
nullptr),
245 span<T, detail::subspan_extent(N, Offset, Count)>{
246 data_ + Offset, Count == dynamic_extent ?
size() - Offset : Count};
248 template<index_type Offset>
249 constexpr
span<T, (N >= Offset ? N - Offset : dynamic_extent)> subspan()
const
252 static_assert(Offset >= 0,
253 "Offset of first element to extract cannot be negative.");
254 static_assert(N == dynamic_extent || N >= Offset,
255 "Offset of first element to extract must be within the static "
257 return RANGES_EXPECT(
size() >= Offset),
258 RANGES_EXPECT((Offset == 0 &&
size() == 0) || data_ !=
nullptr),
260 N >= Offset ? N - Offset
261 : dynamic_extent > {data_ + Offset,
size() - Offset};
265 return RANGES_EXPECT(offset >= 0), RANGES_EXPECT(
size() >= offset),
266 RANGES_EXPECT((offset == 0 &&
size() == 0) || data_ !=
nullptr),
272 return RANGES_EXPECT(offset >= 0), RANGES_EXPECT(cnt >= 0),
273 RANGES_EXPECT(
size() >= offset + cnt),
274 RANGES_EXPECT((offset == 0 && cnt == 0) || data_ !=
nullptr),
278 constexpr pointer data()
const noexcept
283 constexpr index_type size_bytes()
const noexcept
285 return detail::byte_size<T>(
size());
287 constexpr
bool empty()
const noexcept
292 constexpr reference operator[](index_type idx)
const noexcept
294 return RANGES_EXPECT(idx >= 0), RANGES_EXPECT(idx <
size()),
295 RANGES_EXPECT(data_), data_[idx];
298 constexpr iterator begin()
const noexcept
300 return RANGES_EXPECT(!
size() || data_), data_;
302 constexpr iterator end()
const noexcept
304 return RANGES_EXPECT(!
size() || data_), data_ +
size();
315 template(
typename U, index_type M)(
316 requires equality_comparable_with<T, U>)
317 bool operator==(
span<U, M> const & that)
const
319 RANGES_EXPECT(!
size() || data());
320 RANGES_EXPECT(!that.size() || that.data());
321 return ranges::equal(*
this, that);
323 template(
typename U, index_type M)(
324 requires equality_comparable_with<T, U>)
325 bool operator!=(
span<U, M> const & that)
const
327 return !(*
this == that);
330 template(
typename U, index_type M)(
331 requires totally_ordered_with<T, U>)
334 RANGES_EXPECT(!
size() || data());
335 RANGES_EXPECT(!that.size() || that.data());
336 return ranges::lexicographical_compare(*
this, that);
338 template(
typename U, index_type M)(
339 requires totally_ordered_with<T, U>)
344 template(
typename U, index_type M)(
345 requires totally_ordered_with<T, U>)
346 bool operator<=(
span<U, M> const & that)
const
348 return !(that < *
this);
350 template(
typename U, index_type M)(
351 requires totally_ordered_with<T, U>)
352 bool operator>=(
span<U, M> const & that)
const
354 return !(*
this < that);
361 template<
typename T, detail::span_index_t N>
362 RANGES_INLINE_VAR constexpr
bool enable_borrowed_range<span<T, N>> =
true;
364 template<
typename T, detail::span_index_t N>
367 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
368 template(
typename Rng)(
369 requires contiguous_range<Rng>)
373 :
static_cast<detail::span_index_t
>(
377 template<
typename T, detail::span_index_t N>
380 return {
reinterpret_cast<unsigned char const *
>(s.data()), s.size_bytes()};
382 template<
typename T, detail::span_index_t N>
383 span<unsigned char, detail::byte_size<T>(N)> as_writeable_bytes(span<T, N> s) noexcept
385 return {
reinterpret_cast<unsigned char *
>(s.data()), s.size_bytes()};
388 template<
typename ElementType>
389 constexpr span<ElementType> make_span(ElementType * ptr,
390 detail::span_index_t cnt) noexcept
392 return span<ElementType>{ptr, cnt};
394 template<
typename ElementType>
395 constexpr span<ElementType> make_span(ElementType *
first,
396 ElementType * last) noexcept
398 return span<ElementType>{
first, last};
400 template(
typename Rng)(
401 requires contiguous_range<Rng> AND
403 constexpr
span<detail::element_t<Rng>> make_span(Rng && rng) noexcept(
406 return {ranges::data(rng),
407 detail::narrow_cast<detail::span_index_t>(
ranges::size(rng))};
409 template(
typename Rng)(
410 requires contiguous_range<Rng> AND
411 (range_cardinality<Rng>::value >= cardinality()))
413 detail::element_t<Rng>,
414 static_cast<detail::span_index_t
>(
415 range_cardinality<Rng>::
416 value)> make_span(Rng && rng) noexcept(noexcept(ranges::data(rng)))
418 return {ranges::data(rng), range_cardinality<Rng>::value};
424 #include <range/v3/detail/epilogue.hpp>
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition: meta.hpp:2231
Definition: basic_iterator.hpp:532
Definition: traits.hpp:128
Definition: interface.hpp:129