span.hpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Casey Carter 2016-2017
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_VIEW_SPAN_HPP
  14. #define RANGES_V3_VIEW_SPAN_HPP
  15. #include <cstddef>
  16. #include <meta/meta.hpp>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/algorithm/equal.hpp>
  19. #include <range/v3/algorithm/lexicographical_compare.hpp>
  20. #include <range/v3/iterator/reverse_iterator.hpp>
  21. #include <range/v3/range/access.hpp>
  22. #include <range/v3/range/concepts.hpp>
  23. #include <range/v3/range/primitives.hpp>
  24. #include <range/v3/range/traits.hpp>
  25. #include <range/v3/view/interface.hpp>
  26. #include <range/v3/detail/prologue.hpp>
  27. namespace ranges
  28. {
  29. /// \addtogroup group-views
  30. /// @{
  31. /// \cond
  32. namespace detail
  33. {
  34. using span_index_t = std::ptrdiff_t;
  35. } // namespace detail
  36. /// \endcond
  37. constexpr detail::span_index_t dynamic_extent = -1;
  38. /// \cond
  39. namespace detail
  40. {
  41. template(typename To, typename From)(
  42. requires integral<To> AND integral<From>)
  43. constexpr To narrow_cast(From from) noexcept
  44. {
  45. using C = common_type_t<To, From>;
  46. return RANGES_EXPECT((from > 0) == (static_cast<To>(from) > 0)),
  47. RANGES_EXPECT(static_cast<C>(from) ==
  48. static_cast<C>(static_cast<To>(from))),
  49. static_cast<To>(from);
  50. }
  51. template<typename T>
  52. constexpr span_index_t byte_size(span_index_t n) noexcept
  53. {
  54. return n == dynamic_extent ? dynamic_extent
  55. : (RANGES_EXPECT(n >= 0),
  56. RANGES_EXPECT(narrow_cast<std::size_t>(n) <=
  57. PTRDIFF_MAX / sizeof(T)),
  58. n * narrow_cast<span_index_t>(sizeof(T)));
  59. }
  60. template<span_index_t N>
  61. struct span_extent
  62. {
  63. CPP_assert(N >= 0);
  64. constexpr span_extent() noexcept = default;
  65. constexpr span_extent(span_index_t size) noexcept
  66. // this constructor does nothing, the delegation exists only
  67. // to provide a place for the contract check expression.
  68. : span_extent{(RANGES_EXPECT(size == N), tag{})}
  69. {}
  70. constexpr span_index_t size() const noexcept
  71. {
  72. return N;
  73. }
  74. private:
  75. struct tag
  76. {};
  77. constexpr span_extent(tag) noexcept
  78. {}
  79. };
  80. template<>
  81. struct span_extent<dynamic_extent>
  82. {
  83. span_extent() = default;
  84. constexpr span_extent(span_index_t size) noexcept
  85. : size_{((void)RANGES_EXPECT(size >= 0), size)}
  86. {}
  87. constexpr span_index_t size() const noexcept
  88. {
  89. return size_;
  90. }
  91. private:
  92. span_index_t size_ = 0;
  93. };
  94. constexpr span_index_t subspan_extent(span_index_t Extent, span_index_t Offset,
  95. span_index_t Count) noexcept
  96. {
  97. return Count == dynamic_extent && Extent != dynamic_extent ? Extent - Offset
  98. : Count;
  99. }
  100. } // namespace detail
  101. // clang-format off
  102. /// \concept span_compatible_range_
  103. /// \brief The \c span_compatible_range_ concept
  104. template(typename Rng, typename T)(
  105. concept (span_compatible_range_)(Rng, T),
  106. detail::is_convertible<detail::element_t<Rng>(*)[], T(*)[]>::value
  107. );
  108. /// \concept span_compatible_range
  109. /// \brief The \c span_compatible_range concept
  110. template<typename Rng, typename T>
  111. CPP_concept span_compatible_range =
  112. sized_range<Rng> && contiguous_range<Rng> &&
  113. CPP_concept_ref(ranges::span_compatible_range_, Rng, T);
  114. /// \concept span_dynamic_conversion
  115. /// \brief The \c span_dynamic_conversion concept
  116. template<typename Rng, detail::span_index_t N>
  117. CPP_concept span_dynamic_conversion =
  118. N == dynamic_extent ||
  119. range_cardinality<Rng>::value < cardinality();
  120. /// \concept span_static_conversion
  121. /// \brief The \c span_static_conversion concept
  122. template<typename Rng, detail::span_index_t N>
  123. CPP_concept span_static_conversion =
  124. N != dynamic_extent && range_cardinality<Rng>::value == N;
  125. // clang-format on
  126. /// \endcond
  127. template<typename T, detail::span_index_t N = dynamic_extent>
  128. struct RANGES_EMPTY_BASES span
  129. : public view_interface<
  130. span<T, N>, (N == dynamic_extent ? finite : static_cast<cardinality>(N))>
  131. , public detail::span_extent<N>
  132. {
  133. CPP_assert(std::is_object<T>::value);
  134. using element_type = T;
  135. using value_type = meta::_t<std::remove_cv<T>>;
  136. using index_type = detail::span_index_t;
  137. using difference_type = index_type;
  138. using pointer = T *;
  139. using reference = T &;
  140. using iterator = T *;
  141. using reverse_iterator = ranges::reverse_iterator<iterator>;
  142. static constexpr index_type extent = N;
  143. constexpr span() noexcept = default;
  144. constexpr span(pointer ptr, index_type cnt) noexcept
  145. : detail::span_extent<N>{(RANGES_EXPECT(cnt >= 0), cnt)}
  146. , data_{(RANGES_EXPECT(0 == cnt || ptr != nullptr), ptr)}
  147. {}
  148. template<typename = void> // Artificially templatize so that the other
  149. // constructor is preferred for {ptr, 0}
  150. constexpr span(pointer first, pointer last) noexcept
  151. : span{first, last - first}
  152. {}
  153. template(typename Rng)(
  154. requires (!same_as<span, uncvref_t<Rng>>) AND
  155. span_compatible_range<Rng, T> AND
  156. span_dynamic_conversion<Rng, N>)
  157. constexpr span(Rng && rng) noexcept(noexcept(ranges::data(rng),
  158. ranges::size(rng)))
  159. : span{ranges::data(rng), detail::narrow_cast<index_type>(ranges::size(rng))}
  160. {}
  161. template(typename Rng)(
  162. requires (!same_as<span, uncvref_t<Rng>>) AND
  163. span_compatible_range<Rng, T> AND
  164. span_static_conversion<Rng, N>)
  165. constexpr span(Rng && rng) noexcept(noexcept(ranges::data(rng)))
  166. : span{ranges::data(rng), N}
  167. {}
  168. template<index_type Count>
  169. constexpr span<T, Count> first() const noexcept
  170. {
  171. static_assert(Count >= 0, "Count of elements to extract cannot be negative.");
  172. static_assert(
  173. N == dynamic_extent || Count <= N,
  174. "Count of elements to extract must be less than the static span extent.");
  175. return RANGES_EXPECT(Count <= size()),
  176. RANGES_EXPECT(Count == 0 || data_ != nullptr),
  177. span<T, Count>{data_, Count};
  178. }
  179. constexpr span<T> first(index_type cnt) const noexcept
  180. {
  181. return RANGES_EXPECT(cnt >= 0 && cnt <= size()),
  182. RANGES_EXPECT(cnt == 0 || data_ != nullptr), span<T>{data_, cnt};
  183. }
  184. template<index_type Count>
  185. constexpr span<T, Count> last() const noexcept
  186. {
  187. static_assert(Count >= 0, "Count of elements to extract cannot be negative.");
  188. static_assert(
  189. N == dynamic_extent || Count <= N,
  190. "Count of elements to extract must be less than the static span extent.");
  191. return RANGES_EXPECT(Count <= size()),
  192. RANGES_EXPECT((Count == 0 && size() == 0) || data_ != nullptr),
  193. span<T, Count>{data_ + size() - Count, Count};
  194. }
  195. constexpr span<T> last(index_type cnt) const noexcept
  196. {
  197. return RANGES_EXPECT(cnt >= 0 && cnt <= size()),
  198. RANGES_EXPECT((cnt == 0 && size() == 0) || data_ != nullptr),
  199. span<T>{data_ + size() - cnt, cnt};
  200. }
  201. template<index_type Offset, index_type Count>
  202. constexpr span<T, detail::subspan_extent(N, Offset, Count)> subspan() const
  203. noexcept
  204. {
  205. static_assert(Offset >= 0,
  206. "Offset of first element to extract cannot be negative.");
  207. static_assert(Count >= dynamic_extent,
  208. "Count of elements to extract cannot be negative.");
  209. static_assert(
  210. N == dynamic_extent ||
  211. N >= Offset + (Count == dynamic_extent ? 0 : Count),
  212. "Sequence of elements to extract must be within the static span extent.");
  213. return RANGES_EXPECT(size() >=
  214. Offset + (Count == dynamic_extent ? 0 : Count)),
  215. RANGES_EXPECT((Offset == 0 && Count <= 0) || data_ != nullptr),
  216. span<T, detail::subspan_extent(N, Offset, Count)>{
  217. data_ + Offset, Count == dynamic_extent ? size() - Offset : Count};
  218. }
  219. template<index_type Offset>
  220. constexpr span<T, (N >= Offset ? N - Offset : dynamic_extent)> subspan() const
  221. noexcept
  222. {
  223. static_assert(Offset >= 0,
  224. "Offset of first element to extract cannot be negative.");
  225. static_assert(N == dynamic_extent || N >= Offset,
  226. "Offset of first element to extract must be within the static "
  227. "span extent.");
  228. return RANGES_EXPECT(size() >= Offset),
  229. RANGES_EXPECT((Offset == 0 && size() == 0) || data_ != nullptr),
  230. span < T,
  231. N >= Offset ? N - Offset
  232. : dynamic_extent > {data_ + Offset, size() - Offset};
  233. }
  234. constexpr span<T, dynamic_extent> subspan(index_type offset) const noexcept
  235. {
  236. return RANGES_EXPECT(offset >= 0), RANGES_EXPECT(size() >= offset),
  237. RANGES_EXPECT((offset == 0 && size() == 0) || data_ != nullptr),
  238. span<T, dynamic_extent>{data_ + offset, size() - offset};
  239. }
  240. constexpr span<T, dynamic_extent> subspan(index_type offset, index_type cnt) const
  241. noexcept
  242. {
  243. return RANGES_EXPECT(offset >= 0), RANGES_EXPECT(cnt >= 0),
  244. RANGES_EXPECT(size() >= offset + cnt),
  245. RANGES_EXPECT((offset == 0 && cnt == 0) || data_ != nullptr),
  246. span<T, dynamic_extent>{data_ + offset, cnt};
  247. }
  248. constexpr pointer data() const noexcept
  249. {
  250. return data_;
  251. }
  252. using detail::span_extent<N>::size;
  253. constexpr index_type size_bytes() const noexcept
  254. {
  255. return detail::byte_size<T>(size());
  256. }
  257. constexpr bool empty() const noexcept
  258. {
  259. return size() == 0;
  260. }
  261. constexpr reference operator[](index_type idx) const noexcept
  262. {
  263. return RANGES_EXPECT(idx >= 0), RANGES_EXPECT(idx < size()),
  264. RANGES_EXPECT(data_), data_[idx];
  265. }
  266. constexpr iterator begin() const noexcept
  267. {
  268. return RANGES_EXPECT(!size() || data_), data_;
  269. }
  270. constexpr iterator end() const noexcept
  271. {
  272. return RANGES_EXPECT(!size() || data_), data_ + size();
  273. }
  274. constexpr reverse_iterator rbegin() const noexcept
  275. {
  276. return reverse_iterator{end()};
  277. }
  278. constexpr reverse_iterator rend() const noexcept
  279. {
  280. return reverse_iterator{begin()};
  281. }
  282. template(typename U, index_type M)(
  283. requires equality_comparable_with<T, U>)
  284. bool operator==(span<U, M> const & that) const
  285. {
  286. RANGES_EXPECT(!size() || data());
  287. RANGES_EXPECT(!that.size() || that.data());
  288. return ranges::equal(*this, that);
  289. }
  290. template(typename U, index_type M)(
  291. requires equality_comparable_with<T, U>)
  292. bool operator!=(span<U, M> const & that) const
  293. {
  294. return !(*this == that);
  295. }
  296. template(typename U, index_type M)(
  297. requires totally_ordered_with<T, U>)
  298. bool operator<(span<U, M> const & that) const
  299. {
  300. RANGES_EXPECT(!size() || data());
  301. RANGES_EXPECT(!that.size() || that.data());
  302. return ranges::lexicographical_compare(*this, that);
  303. }
  304. template(typename U, index_type M)(
  305. requires totally_ordered_with<T, U>)
  306. bool operator>(span<U, M> const & that) const
  307. {
  308. return that < *this;
  309. }
  310. template(typename U, index_type M)(
  311. requires totally_ordered_with<T, U>)
  312. bool operator<=(span<U, M> const & that) const
  313. {
  314. return !(that < *this);
  315. }
  316. template(typename U, index_type M)(
  317. requires totally_ordered_with<T, U>)
  318. bool operator>=(span<U, M> const & that) const
  319. {
  320. return !(*this < that);
  321. }
  322. private:
  323. T * data_ = nullptr;
  324. };
  325. template<typename T, detail::span_index_t N>
  326. RANGES_INLINE_VAR constexpr bool enable_borrowed_range<span<T, N>> = true;
  327. template<typename T, detail::span_index_t N>
  328. constexpr detail::span_index_t span<T, N>::extent;
  329. #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
  330. template(typename Rng)(
  331. requires contiguous_range<Rng>)
  332. span(Rng && rng)
  333. ->span<detail::element_t<Rng>, (range_cardinality<Rng>::value < cardinality()
  334. ? dynamic_extent
  335. : static_cast<detail::span_index_t>(
  336. range_cardinality<Rng>::value))>;
  337. #endif
  338. template<typename T, detail::span_index_t N>
  339. span<unsigned char const, detail::byte_size<T>(N)> as_bytes(span<T, N> s) noexcept
  340. {
  341. return {reinterpret_cast<unsigned char const *>(s.data()), s.size_bytes()};
  342. }
  343. template<typename T, detail::span_index_t N>
  344. span<unsigned char, detail::byte_size<T>(N)> as_writeable_bytes(span<T, N> s) noexcept
  345. {
  346. return {reinterpret_cast<unsigned char *>(s.data()), s.size_bytes()};
  347. }
  348. template<typename ElementType>
  349. constexpr span<ElementType> make_span(ElementType * ptr,
  350. detail::span_index_t cnt) noexcept
  351. {
  352. return span<ElementType>{ptr, cnt};
  353. }
  354. template<typename ElementType>
  355. constexpr span<ElementType> make_span(ElementType * first,
  356. ElementType * last) noexcept
  357. {
  358. return span<ElementType>{first, last};
  359. }
  360. template(typename Rng)(
  361. requires contiguous_range<Rng> AND
  362. (range_cardinality<Rng>::value < cardinality())) //
  363. constexpr span<detail::element_t<Rng>> make_span(Rng && rng) noexcept(
  364. noexcept(ranges::data(rng), ranges::size(rng)))
  365. {
  366. return {ranges::data(rng),
  367. detail::narrow_cast<detail::span_index_t>(ranges::size(rng))};
  368. }
  369. template(typename Rng)(
  370. requires contiguous_range<Rng> AND
  371. (range_cardinality<Rng>::value >= cardinality())) //
  372. constexpr span<
  373. detail::element_t<Rng>,
  374. static_cast<detail::span_index_t>(
  375. range_cardinality<Rng>::
  376. value)> make_span(Rng && rng) noexcept(noexcept(ranges::data(rng)))
  377. {
  378. return {ranges::data(rng), range_cardinality<Rng>::value};
  379. }
  380. /// @}
  381. } // namespace ranges
  382. #include <range/v3/detail/epilogue.hpp>
  383. #endif // RANGES_V3_VIEW_SPAN_HPP