span 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. // Components for manipulating non-owning sequences of objects -*- C++ -*-
  2. // Copyright (C) 2019-2022 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. // member constants
  114. static constexpr size_t extent = _Extent;
  115. // constructors, copy and assignment
  116. constexpr
  117. span() noexcept
  118. requires ((_Extent + 1u) <= 1u)
  119. : _M_ptr(nullptr), _M_extent(0)
  120. { }
  121. template<contiguous_iterator _It>
  122. requires __is_compatible_ref<iter_reference_t<_It>>::value
  123. constexpr explicit(extent != dynamic_extent)
  124. span(_It __first, size_type __count)
  125. noexcept
  126. : _M_ptr(std::to_address(__first)), _M_extent(__count)
  127. {
  128. if constexpr (_Extent != dynamic_extent)
  129. {
  130. __glibcxx_assert(__count == _Extent);
  131. }
  132. __glibcxx_requires_valid_range(__first, __first + __count);
  133. }
  134. template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
  135. requires __is_compatible_ref<iter_reference_t<_It>>::value
  136. && (!is_convertible_v<_End, size_type>)
  137. constexpr explicit(extent != dynamic_extent)
  138. span(_It __first, _End __last)
  139. noexcept(noexcept(__last - __first))
  140. : _M_ptr(std::to_address(__first)),
  141. _M_extent(static_cast<size_type>(__last - __first))
  142. {
  143. if constexpr (_Extent != dynamic_extent)
  144. {
  145. __glibcxx_assert((__last - __first) == _Extent);
  146. }
  147. __glibcxx_requires_valid_range(__first, __last);
  148. }
  149. template<size_t _ArrayExtent>
  150. requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
  151. constexpr
  152. span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
  153. : span(static_cast<pointer>(__arr), _ArrayExtent)
  154. { }
  155. template<typename _Tp, size_t _ArrayExtent>
  156. requires __is_compatible_array<_Tp, _ArrayExtent>::value
  157. constexpr
  158. span(array<_Tp, _ArrayExtent>& __arr) noexcept
  159. : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
  160. { }
  161. template<typename _Tp, size_t _ArrayExtent>
  162. requires __is_compatible_array<const _Tp, _ArrayExtent>::value
  163. constexpr
  164. span(const array<_Tp, _ArrayExtent>& __arr) noexcept
  165. : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
  166. { }
  167. template<typename _Range>
  168. requires (!__detail::__is_span<remove_cvref_t<_Range>>)
  169. && (!__detail::__is_std_array<remove_cvref_t<_Range>>)
  170. && (!is_array_v<remove_cvref_t<_Range>>)
  171. && ranges::contiguous_range<_Range> && ranges::sized_range<_Range>
  172. && (ranges::borrowed_range<_Range> || is_const_v<element_type>)
  173. && __is_compatible_ref<ranges::range_reference_t<_Range>>::value
  174. constexpr explicit(extent != dynamic_extent)
  175. span(_Range&& __range)
  176. noexcept(noexcept(ranges::data(__range))
  177. && noexcept(ranges::size(__range)))
  178. : span(ranges::data(__range), ranges::size(__range))
  179. {
  180. if constexpr (extent != dynamic_extent)
  181. {
  182. __glibcxx_assert(ranges::size(__range) == extent);
  183. }
  184. }
  185. constexpr
  186. span(const span&) noexcept = default;
  187. template<typename _OType, size_t _OExtent>
  188. requires (_Extent == dynamic_extent || _OExtent == dynamic_extent
  189. || _Extent == _OExtent)
  190. && (__is_array_convertible<_Type, _OType>::value)
  191. constexpr
  192. explicit(extent != dynamic_extent && _OExtent == dynamic_extent)
  193. span(const span<_OType, _OExtent>& __s) noexcept
  194. : _M_extent(__s.size()), _M_ptr(__s.data())
  195. {
  196. if constexpr (extent != dynamic_extent)
  197. {
  198. __glibcxx_assert(__s.size() == extent);
  199. }
  200. }
  201. ~span() noexcept = default;
  202. constexpr span&
  203. operator=(const span&) noexcept = default;
  204. // observers
  205. constexpr size_type
  206. size() const noexcept
  207. { return this->_M_extent._M_extent(); }
  208. constexpr size_type
  209. size_bytes() const noexcept
  210. { return this->_M_extent._M_extent() * sizeof(element_type); }
  211. [[nodiscard]] constexpr bool
  212. empty() const noexcept
  213. { return size() == 0; }
  214. // element access
  215. constexpr reference
  216. front() const noexcept
  217. {
  218. __glibcxx_assert(!empty());
  219. return *this->_M_ptr;
  220. }
  221. constexpr reference
  222. back() const noexcept
  223. {
  224. __glibcxx_assert(!empty());
  225. return *(this->_M_ptr + (size() - 1));
  226. }
  227. constexpr reference
  228. operator[](size_type __idx) const noexcept
  229. {
  230. __glibcxx_assert(__idx < size());
  231. return *(this->_M_ptr + __idx);
  232. }
  233. constexpr pointer
  234. data() const noexcept
  235. { return this->_M_ptr; }
  236. // iterator support
  237. constexpr iterator
  238. begin() const noexcept
  239. { return iterator(this->_M_ptr); }
  240. constexpr iterator
  241. end() const noexcept
  242. { return iterator(this->_M_ptr + this->size()); }
  243. constexpr reverse_iterator
  244. rbegin() const noexcept
  245. { return reverse_iterator(this->end()); }
  246. constexpr reverse_iterator
  247. rend() const noexcept
  248. { return reverse_iterator(this->begin()); }
  249. // subviews
  250. template<size_t _Count>
  251. constexpr span<element_type, _Count>
  252. first() const noexcept
  253. {
  254. if constexpr (_Extent == dynamic_extent)
  255. __glibcxx_assert(_Count <= size());
  256. else
  257. static_assert(_Count <= extent);
  258. using _Sp = span<element_type, _Count>;
  259. return _Sp{ this->data(), _Count };
  260. }
  261. constexpr span<element_type, dynamic_extent>
  262. first(size_type __count) const noexcept
  263. {
  264. __glibcxx_assert(__count <= size());
  265. return { this->data(), __count };
  266. }
  267. template<size_t _Count>
  268. constexpr span<element_type, _Count>
  269. last() const noexcept
  270. {
  271. if constexpr (_Extent == dynamic_extent)
  272. __glibcxx_assert(_Count <= size());
  273. else
  274. static_assert(_Count <= extent);
  275. using _Sp = span<element_type, _Count>;
  276. return _Sp{ this->data() + (this->size() - _Count), _Count };
  277. }
  278. constexpr span<element_type, dynamic_extent>
  279. last(size_type __count) const noexcept
  280. {
  281. __glibcxx_assert(__count <= size());
  282. return { this->data() + (this->size() - __count), __count };
  283. }
  284. template<size_t _Offset, size_t _Count = dynamic_extent>
  285. constexpr auto
  286. subspan() const noexcept
  287. -> span<element_type, _S_subspan_extent<_Offset, _Count>()>
  288. {
  289. if constexpr (_Extent == dynamic_extent)
  290. {
  291. __glibcxx_assert(_Offset <= size());
  292. }
  293. else
  294. static_assert(_Offset <= extent);
  295. using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>;
  296. if constexpr (_Count == dynamic_extent)
  297. return _Sp{ this->data() + _Offset, this->size() - _Offset };
  298. else
  299. {
  300. if constexpr (_Extent == dynamic_extent)
  301. {
  302. __glibcxx_assert(_Count <= size());
  303. __glibcxx_assert(_Count <= (size() - _Offset));
  304. }
  305. else
  306. {
  307. static_assert(_Count <= extent);
  308. static_assert(_Count <= (extent - _Offset));
  309. }
  310. return _Sp{ this->data() + _Offset, _Count };
  311. }
  312. }
  313. constexpr span<element_type, dynamic_extent>
  314. subspan(size_type __offset, size_type __count = dynamic_extent) const
  315. noexcept
  316. {
  317. __glibcxx_assert(__offset <= size());
  318. if (__count == dynamic_extent)
  319. __count = this->size() - __offset;
  320. else
  321. {
  322. __glibcxx_assert(__count <= size());
  323. __glibcxx_assert(__offset + __count <= size());
  324. }
  325. return {this->data() + __offset, __count};
  326. }
  327. private:
  328. pointer _M_ptr;
  329. [[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
  330. };
  331. // deduction guides
  332. template<typename _Type, size_t _ArrayExtent>
  333. span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
  334. template<typename _Type, size_t _ArrayExtent>
  335. span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>;
  336. template<typename _Type, size_t _ArrayExtent>
  337. span(const array<_Type, _ArrayExtent>&)
  338. -> span<const _Type, _ArrayExtent>;
  339. template<contiguous_iterator _Iter, typename _End>
  340. span(_Iter, _End)
  341. -> span<remove_reference_t<iter_reference_t<_Iter>>>;
  342. template<ranges::contiguous_range _Range>
  343. span(_Range &&)
  344. -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
  345. template<typename _Type, size_t _Extent>
  346. inline
  347. span<const byte, _Extent == dynamic_extent
  348. ? dynamic_extent : _Extent * sizeof(_Type)>
  349. as_bytes(span<_Type, _Extent> __sp) noexcept
  350. {
  351. auto data = reinterpret_cast<const byte*>(__sp.data());
  352. auto size = __sp.size_bytes();
  353. constexpr auto extent = _Extent == dynamic_extent
  354. ? dynamic_extent : _Extent * sizeof(_Type);
  355. return span<const byte, extent>{data, size};
  356. }
  357. template<typename _Type, size_t _Extent>
  358. requires (!is_const_v<_Type>)
  359. inline
  360. span<byte, _Extent == dynamic_extent
  361. ? dynamic_extent : _Extent * sizeof(_Type)>
  362. as_writable_bytes(span<_Type, _Extent> __sp) noexcept
  363. {
  364. auto data = reinterpret_cast<byte*>(__sp.data());
  365. auto size = __sp.size_bytes();
  366. constexpr auto extent = _Extent == dynamic_extent
  367. ? dynamic_extent : _Extent * sizeof(_Type);
  368. return span<byte, extent>{data, size};
  369. }
  370. namespace ranges
  371. {
  372. // Opt-in to borrowed_range concept
  373. template<typename _ElementType, size_t _Extent>
  374. inline constexpr bool
  375. enable_borrowed_range<span<_ElementType, _Extent>> = true;
  376. // Opt-in to view concept
  377. template<typename _ElementType, size_t _Extent>
  378. inline constexpr bool
  379. enable_view<span<_ElementType, _Extent>> = true;
  380. }
  381. _GLIBCXX_END_NAMESPACE_VERSION
  382. } // namespace std
  383. #endif // concepts
  384. #endif // C++20
  385. #endif // _GLIBCXX_SPAN