span 13 KB

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