span 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. // Components for manipulating non-owning sequences of objects -*- C++ -*-
  2. // Copyright (C) 2019-2023 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file span
  21. * This is a Standard C++ Library header.
  22. */
  23. //
  24. // P0122 span library
  25. // Contributed by ThePhD
  26. //
  27. #ifndef _GLIBCXX_SPAN
  28. #define _GLIBCXX_SPAN 1
  29. #pragma GCC system_header
  30. #if __cplusplus > 201703L
  31. #include <array>
  32. #include <cstddef>
  33. #include <bits/stl_iterator.h>
  34. #include <bits/ranges_base.h>
  35. #if __cpp_lib_concepts
  36. namespace std _GLIBCXX_VISIBILITY(default)
  37. {
  38. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  39. #define __cpp_lib_span 202002L
  40. inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
  41. template<typename _Type, size_t _Extent>
  42. class span;
  43. namespace __detail
  44. {
  45. template<typename _Tp>
  46. inline constexpr bool __is_span = false;
  47. template<typename _Tp, size_t _Num>
  48. inline constexpr bool __is_span<span<_Tp, _Num>> = true;
  49. template<typename _Tp>
  50. inline constexpr bool __is_std_array = false;
  51. template<typename _Tp, size_t _Num>
  52. inline constexpr bool __is_std_array<std::array<_Tp, _Num>> = true;
  53. template<size_t _Extent>
  54. class __extent_storage
  55. {
  56. public:
  57. constexpr
  58. __extent_storage(size_t) noexcept
  59. { }
  60. static constexpr size_t
  61. _M_extent() noexcept
  62. { return _Extent; }
  63. };
  64. template<>
  65. class __extent_storage<dynamic_extent>
  66. {
  67. public:
  68. constexpr
  69. __extent_storage(size_t __extent) noexcept
  70. : _M_extent_value(__extent)
  71. { }
  72. constexpr size_t
  73. _M_extent() const noexcept
  74. { return this->_M_extent_value; }
  75. private:
  76. size_t _M_extent_value;
  77. };
  78. } // namespace __detail
  79. template<typename _Type, size_t _Extent = dynamic_extent>
  80. class span
  81. {
  82. template<size_t _Offset, size_t _Count>
  83. static constexpr size_t
  84. _S_subspan_extent()
  85. {
  86. if constexpr (_Count != dynamic_extent)
  87. return _Count;
  88. else if constexpr (extent != dynamic_extent)
  89. return _Extent - _Offset;
  90. else
  91. return dynamic_extent;
  92. }
  93. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  94. // 3255. span's array constructor is too strict
  95. template<typename _Tp, size_t _ArrayExtent>
  96. requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
  97. using __is_compatible_array = __is_array_convertible<_Type, _Tp>;
  98. template<typename _Ref>
  99. using __is_compatible_ref
  100. = __is_array_convertible<_Type, remove_reference_t<_Ref>>;
  101. public:
  102. // member types
  103. using element_type = _Type;
  104. using value_type = remove_cv_t<_Type>;
  105. using size_type = size_t;
  106. using difference_type = ptrdiff_t;
  107. using pointer = _Type*;
  108. using const_pointer = const _Type*;
  109. using reference = element_type&;
  110. using const_reference = const element_type&;
  111. using iterator = __gnu_cxx::__normal_iterator<pointer, span>;
  112. using reverse_iterator = std::reverse_iterator<iterator>;
  113. #if __cplusplus > 202002L
  114. using const_iterator = std::const_iterator<iterator>;
  115. using const_reverse_iterator = std::const_iterator<reverse_iterator>;
  116. #endif
  117. // member constants
  118. static constexpr size_t extent = _Extent;
  119. // constructors, copy and assignment
  120. constexpr
  121. span() noexcept
  122. requires (_Extent == dynamic_extent || _Extent == 0)
  123. : _M_ptr(nullptr), _M_extent(0)
  124. { }
  125. template<contiguous_iterator _It>
  126. requires __is_compatible_ref<iter_reference_t<_It>>::value
  127. constexpr explicit(extent != dynamic_extent)
  128. span(_It __first, size_type __count)
  129. noexcept
  130. : _M_ptr(std::to_address(__first)), _M_extent(__count)
  131. {
  132. if constexpr (_Extent != dynamic_extent)
  133. {
  134. __glibcxx_assert(__count == _Extent);
  135. }
  136. __glibcxx_requires_valid_range(__first, __first + __count);
  137. }
  138. template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
  139. requires __is_compatible_ref<iter_reference_t<_It>>::value
  140. && (!is_convertible_v<_End, size_type>)
  141. constexpr explicit(extent != dynamic_extent)
  142. span(_It __first, _End __last)
  143. noexcept(noexcept(__last - __first))
  144. : _M_ptr(std::to_address(__first)),
  145. _M_extent(static_cast<size_type>(__last - __first))
  146. {
  147. if constexpr (_Extent != dynamic_extent)
  148. {
  149. __glibcxx_assert((__last - __first) == _Extent);
  150. }
  151. __glibcxx_requires_valid_range(__first, __last);
  152. }
  153. template<size_t _ArrayExtent>
  154. requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
  155. constexpr
  156. span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
  157. : span(static_cast<pointer>(__arr), _ArrayExtent)
  158. { }
  159. template<typename _Tp, size_t _ArrayExtent>
  160. requires __is_compatible_array<_Tp, _ArrayExtent>::value
  161. constexpr
  162. span(array<_Tp, _ArrayExtent>& __arr) noexcept
  163. : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
  164. { }
  165. template<typename _Tp, size_t _ArrayExtent>
  166. requires __is_compatible_array<const _Tp, _ArrayExtent>::value
  167. constexpr
  168. span(const array<_Tp, _ArrayExtent>& __arr) noexcept
  169. : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
  170. { }
  171. template<typename _Range>
  172. requires (!__detail::__is_span<remove_cvref_t<_Range>>)
  173. && (!__detail::__is_std_array<remove_cvref_t<_Range>>)
  174. && (!is_array_v<remove_cvref_t<_Range>>)
  175. && ranges::contiguous_range<_Range> && ranges::sized_range<_Range>
  176. && (ranges::borrowed_range<_Range> || is_const_v<element_type>)
  177. && __is_compatible_ref<ranges::range_reference_t<_Range>>::value
  178. constexpr explicit(extent != dynamic_extent)
  179. span(_Range&& __range)
  180. noexcept(noexcept(ranges::data(__range))
  181. && noexcept(ranges::size(__range)))
  182. : span(ranges::data(__range), ranges::size(__range))
  183. {
  184. if constexpr (extent != dynamic_extent)
  185. {
  186. __glibcxx_assert(ranges::size(__range) == extent);
  187. }
  188. }
  189. constexpr
  190. span(const span&) noexcept = default;
  191. template<typename _OType, size_t _OExtent>
  192. requires (_Extent == dynamic_extent || _OExtent == dynamic_extent
  193. || _Extent == _OExtent)
  194. && (__is_array_convertible<_Type, _OType>::value)
  195. constexpr
  196. explicit(extent != dynamic_extent && _OExtent == dynamic_extent)
  197. span(const span<_OType, _OExtent>& __s) noexcept
  198. : _M_extent(__s.size()), _M_ptr(__s.data())
  199. {
  200. if constexpr (extent != dynamic_extent)
  201. {
  202. __glibcxx_assert(__s.size() == extent);
  203. }
  204. }
  205. ~span() noexcept = default;
  206. constexpr span&
  207. operator=(const span&) noexcept = default;
  208. // observers
  209. [[nodiscard]]
  210. constexpr size_type
  211. size() const noexcept
  212. { return this->_M_extent._M_extent(); }
  213. [[nodiscard]]
  214. constexpr size_type
  215. size_bytes() const noexcept
  216. { return this->_M_extent._M_extent() * sizeof(element_type); }
  217. [[nodiscard]]
  218. constexpr bool
  219. empty() const noexcept
  220. { return size() == 0; }
  221. // element access
  222. [[nodiscard]]
  223. constexpr reference
  224. front() const noexcept
  225. {
  226. __glibcxx_assert(!empty());
  227. return *this->_M_ptr;
  228. }
  229. [[nodiscard]]
  230. constexpr reference
  231. back() const noexcept
  232. {
  233. __glibcxx_assert(!empty());
  234. return *(this->_M_ptr + (size() - 1));
  235. }
  236. [[nodiscard]]
  237. constexpr reference
  238. operator[](size_type __idx) const noexcept
  239. {
  240. __glibcxx_assert(__idx < size());
  241. return *(this->_M_ptr + __idx);
  242. }
  243. [[nodiscard]]
  244. constexpr pointer
  245. data() const noexcept
  246. { return this->_M_ptr; }
  247. // iterator support
  248. [[nodiscard]]
  249. constexpr iterator
  250. begin() const noexcept
  251. { return iterator(this->_M_ptr); }
  252. [[nodiscard]]
  253. constexpr iterator
  254. end() const noexcept
  255. { return iterator(this->_M_ptr + this->size()); }
  256. [[nodiscard]]
  257. constexpr reverse_iterator
  258. rbegin() const noexcept
  259. { return reverse_iterator(this->end()); }
  260. [[nodiscard]]
  261. constexpr reverse_iterator
  262. rend() const noexcept
  263. { return reverse_iterator(this->begin()); }
  264. #if __cplusplus > 202002L
  265. [[nodiscard]]
  266. constexpr const_iterator
  267. cbegin() const noexcept
  268. { return begin(); }
  269. [[nodiscard]]
  270. constexpr const_iterator
  271. cend() const noexcept
  272. { return end(); }
  273. [[nodiscard]]
  274. constexpr const_reverse_iterator
  275. crbegin() const noexcept
  276. { return rbegin(); }
  277. [[nodiscard]]
  278. constexpr const_reverse_iterator
  279. crend() const noexcept
  280. { return rend(); }
  281. #endif
  282. // subviews
  283. template<size_t _Count>
  284. [[nodiscard]]
  285. constexpr span<element_type, _Count>
  286. first() const noexcept
  287. {
  288. if constexpr (_Extent == dynamic_extent)
  289. __glibcxx_assert(_Count <= size());
  290. else
  291. static_assert(_Count <= extent);
  292. using _Sp = span<element_type, _Count>;
  293. return _Sp{ this->data(), _Count };
  294. }
  295. [[nodiscard]]
  296. constexpr span<element_type, dynamic_extent>
  297. first(size_type __count) const noexcept
  298. {
  299. __glibcxx_assert(__count <= size());
  300. return { this->data(), __count };
  301. }
  302. template<size_t _Count>
  303. [[nodiscard]]
  304. constexpr span<element_type, _Count>
  305. last() const noexcept
  306. {
  307. if constexpr (_Extent == dynamic_extent)
  308. __glibcxx_assert(_Count <= size());
  309. else
  310. static_assert(_Count <= extent);
  311. using _Sp = span<element_type, _Count>;
  312. return _Sp{ this->data() + (this->size() - _Count), _Count };
  313. }
  314. [[nodiscard]]
  315. constexpr span<element_type, dynamic_extent>
  316. last(size_type __count) const noexcept
  317. {
  318. __glibcxx_assert(__count <= size());
  319. return { this->data() + (this->size() - __count), __count };
  320. }
  321. template<size_t _Offset, size_t _Count = dynamic_extent>
  322. [[nodiscard]]
  323. constexpr auto
  324. subspan() const noexcept
  325. -> span<element_type, _S_subspan_extent<_Offset, _Count>()>
  326. {
  327. if constexpr (_Extent == dynamic_extent)
  328. {
  329. __glibcxx_assert(_Offset <= size());
  330. }
  331. else
  332. static_assert(_Offset <= extent);
  333. using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>;
  334. if constexpr (_Count == dynamic_extent)
  335. return _Sp{ this->data() + _Offset, this->size() - _Offset };
  336. else
  337. {
  338. if constexpr (_Extent == dynamic_extent)
  339. {
  340. __glibcxx_assert(_Count <= size());
  341. __glibcxx_assert(_Count <= (size() - _Offset));
  342. }
  343. else
  344. {
  345. static_assert(_Count <= extent);
  346. static_assert(_Count <= (extent - _Offset));
  347. }
  348. return _Sp{ this->data() + _Offset, _Count };
  349. }
  350. }
  351. [[nodiscard]]
  352. constexpr span<element_type, dynamic_extent>
  353. subspan(size_type __offset, size_type __count = dynamic_extent) const
  354. noexcept
  355. {
  356. __glibcxx_assert(__offset <= size());
  357. if (__count == dynamic_extent)
  358. __count = this->size() - __offset;
  359. else
  360. {
  361. __glibcxx_assert(__count <= size());
  362. __glibcxx_assert(__offset + __count <= size());
  363. }
  364. return {this->data() + __offset, __count};
  365. }
  366. private:
  367. pointer _M_ptr;
  368. [[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
  369. };
  370. // deduction guides
  371. template<typename _Type, size_t _ArrayExtent>
  372. span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
  373. template<typename _Type, size_t _ArrayExtent>
  374. span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>;
  375. template<typename _Type, size_t _ArrayExtent>
  376. span(const array<_Type, _ArrayExtent>&)
  377. -> span<const _Type, _ArrayExtent>;
  378. template<contiguous_iterator _Iter, typename _End>
  379. span(_Iter, _End)
  380. -> span<remove_reference_t<iter_reference_t<_Iter>>>;
  381. template<ranges::contiguous_range _Range>
  382. span(_Range &&)
  383. -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
  384. template<typename _Type, size_t _Extent>
  385. [[nodiscard]]
  386. inline
  387. span<const byte, _Extent == dynamic_extent
  388. ? dynamic_extent : _Extent * sizeof(_Type)>
  389. as_bytes(span<_Type, _Extent> __sp) noexcept
  390. {
  391. auto data = reinterpret_cast<const byte*>(__sp.data());
  392. auto size = __sp.size_bytes();
  393. constexpr auto extent = _Extent == dynamic_extent
  394. ? dynamic_extent : _Extent * sizeof(_Type);
  395. return span<const byte, extent>{data, size};
  396. }
  397. template<typename _Type, size_t _Extent>
  398. requires (!is_const_v<_Type>)
  399. inline
  400. span<byte, _Extent == dynamic_extent
  401. ? dynamic_extent : _Extent * sizeof(_Type)>
  402. as_writable_bytes [[nodiscard]] (span<_Type, _Extent> __sp) noexcept
  403. {
  404. auto data = reinterpret_cast<byte*>(__sp.data());
  405. auto size = __sp.size_bytes();
  406. constexpr auto extent = _Extent == dynamic_extent
  407. ? dynamic_extent : _Extent * sizeof(_Type);
  408. return span<byte, extent>{data, size};
  409. }
  410. namespace ranges
  411. {
  412. // Opt-in to borrowed_range concept
  413. template<typename _ElementType, size_t _Extent>
  414. inline constexpr bool
  415. enable_borrowed_range<span<_ElementType, _Extent>> = true;
  416. // Opt-in to view concept
  417. template<typename _ElementType, size_t _Extent>
  418. inline constexpr bool
  419. enable_view<span<_ElementType, _Extent>> = true;
  420. }
  421. _GLIBCXX_END_NAMESPACE_VERSION
  422. } // namespace std
  423. #endif // concepts
  424. #endif // C++20
  425. #endif // _GLIBCXX_SPAN