span 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2015 Microsoft Corporation. All rights reserved.
  4. //
  5. // This code is licensed under the MIT License (MIT).
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  8. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  9. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  10. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  11. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  12. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  13. // THE SOFTWARE.
  14. //
  15. ///////////////////////////////////////////////////////////////////////////////
  16. #ifndef GSL_SPAN_H
  17. #define GSL_SPAN_H
  18. #include <gsl/gsl_assert> // for Expects
  19. #include <gsl/gsl_byte> // for byte
  20. #include <array> // for array
  21. #include <cstddef> // for ptrdiff_t, size_t, nullptr_t
  22. #include <iterator> // for reverse_iterator, distance, random_access_...
  23. #include <type_traits> // for enable_if_t, declval, is_convertible, inte...
  24. #if defined(_MSC_VER) && !defined(__clang__)
  25. #pragma warning(push)
  26. // turn off some warnings that are noisy about our Expects statements
  27. #pragma warning(disable : 4127) // conditional expression is constant
  28. #pragma warning( \
  29. disable : 4146) // unary minus operator applied to unsigned type, result still unsigned
  30. #pragma warning(disable : 4702) // unreachable code
  31. // Turn MSVC /analyze rules that generate too much noise. TODO: fix in the tool.
  32. #pragma warning(disable : 26495) // uninitalized member when constructor calls constructor
  33. #pragma warning(disable : 26446) // parser bug does not allow attributes on some templates
  34. #endif // _MSC_VER
  35. // See if we have enough C++17 power to use a static constexpr data member
  36. // without needing an out-of-line definition
  37. #if !(defined(__cplusplus) && (__cplusplus >= 201703L))
  38. #define GSL_USE_STATIC_CONSTEXPR_WORKAROUND
  39. #endif // !(defined(__cplusplus) && (__cplusplus >= 201703L))
  40. // GCC 7 does not like the signed unsigned missmatch (size_t ptrdiff_t)
  41. // While there is a conversion from signed to unsigned, it happens at
  42. // compiletime, so the compiler wouldn't have to warn indiscriminately, but
  43. // could check if the source value actually doesn't fit into the target type
  44. // and only warn in those cases.
  45. #if defined(__GNUC__) && __GNUC__ > 6
  46. #pragma GCC diagnostic push
  47. #pragma GCC diagnostic ignored "-Wsign-conversion"
  48. #endif
  49. namespace gsl
  50. {
  51. // [views.constants], constants
  52. constexpr const std::size_t dynamic_extent = static_cast<std::size_t>(-1);
  53. template <class ElementType, std::size_t Extent = dynamic_extent>
  54. class span;
  55. // implementation details
  56. namespace details
  57. {
  58. template <class T>
  59. struct is_span_oracle : std::false_type
  60. {
  61. };
  62. template <class ElementType, std::size_t Extent>
  63. struct is_span_oracle<gsl::span<ElementType, Extent>> : std::true_type
  64. {
  65. };
  66. template <class T>
  67. struct is_span : public is_span_oracle<std::remove_cv_t<T>>
  68. {
  69. };
  70. template <class T>
  71. struct is_std_array_oracle : std::false_type
  72. {
  73. };
  74. template <class ElementType, std::size_t Extent>
  75. struct is_std_array_oracle<std::array<ElementType, Extent>> : std::true_type
  76. {
  77. };
  78. template <class T>
  79. struct is_std_array : is_std_array_oracle<std::remove_cv_t<T>>
  80. {
  81. };
  82. template <std::size_t From, std::size_t To>
  83. struct is_allowed_extent_conversion
  84. : std::integral_constant<bool, From == To || To == gsl::dynamic_extent>
  85. {
  86. };
  87. template <class From, class To>
  88. struct is_allowed_element_type_conversion
  89. : std::integral_constant<bool, std::is_convertible<From (*)[], To (*)[]>::value>
  90. {
  91. };
  92. template <class Type>
  93. class span_iterator
  94. {
  95. public:
  96. using iterator_category = std::random_access_iterator_tag;
  97. using value_type = std::remove_cv_t<Type>;
  98. using difference_type = std::ptrdiff_t;
  99. using pointer = Type*;
  100. using reference = Type&;
  101. #ifdef _MSC_VER
  102. using _Unchecked_type = pointer;
  103. #endif // _MSC_VER
  104. constexpr span_iterator() = default;
  105. constexpr span_iterator(pointer begin, pointer end, pointer current)
  106. : begin_(begin), end_(end), current_(current)
  107. {}
  108. constexpr operator span_iterator<const Type>() const noexcept
  109. {
  110. return {begin_, end_, current_};
  111. }
  112. constexpr reference operator*() const noexcept
  113. {
  114. Expects(begin_ && end_);
  115. Expects(begin_ <= current_ && current_ < end_);
  116. return *current_;
  117. }
  118. constexpr pointer operator->() const noexcept
  119. {
  120. Expects(begin_ && end_);
  121. Expects(begin_ <= current_ && current_ < end_);
  122. return current_;
  123. }
  124. constexpr span_iterator& operator++() noexcept
  125. {
  126. Expects(begin_ && current_ && end_);
  127. Expects(current_ < end_);
  128. ++current_;
  129. return *this;
  130. }
  131. constexpr span_iterator operator++(int) noexcept
  132. {
  133. span_iterator ret = *this;
  134. ++*this;
  135. return ret;
  136. }
  137. constexpr span_iterator& operator--() noexcept
  138. {
  139. Expects(begin_ && end_);
  140. Expects(begin_ < current_);
  141. --current_;
  142. return *this;
  143. }
  144. constexpr span_iterator operator--(int) noexcept
  145. {
  146. span_iterator ret = *this;
  147. --*this;
  148. return ret;
  149. }
  150. constexpr span_iterator& operator+=(const difference_type n) noexcept
  151. {
  152. if (n != 0) Expects(begin_ && current_ && end_);
  153. if (n > 0) Expects(end_ - current_ >= n);
  154. if (n < 0) Expects(current_ - begin_ >= -n);
  155. current_ += n;
  156. return *this;
  157. }
  158. constexpr span_iterator operator+(const difference_type n) const noexcept
  159. {
  160. span_iterator ret = *this;
  161. ret += n;
  162. return ret;
  163. }
  164. friend constexpr span_iterator operator+(const difference_type n,
  165. const span_iterator& rhs) noexcept
  166. {
  167. return rhs + n;
  168. }
  169. constexpr span_iterator& operator-=(const difference_type n) noexcept
  170. {
  171. if (n != 0) Expects(begin_ && current_ && end_);
  172. if (n > 0) Expects(current_ - begin_ >= n);
  173. if (n < 0) Expects(end_ - current_ >= -n);
  174. current_ -= n;
  175. return *this;
  176. }
  177. constexpr span_iterator operator-(const difference_type n) const noexcept
  178. {
  179. span_iterator ret = *this;
  180. ret -= n;
  181. return ret;
  182. }
  183. template <
  184. class Type2,
  185. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  186. constexpr difference_type operator-(const span_iterator<Type2>& rhs) const noexcept
  187. {
  188. Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
  189. return current_ - rhs.current_;
  190. }
  191. constexpr reference operator[](const difference_type n) const noexcept
  192. {
  193. return *(*this + n);
  194. }
  195. template <
  196. class Type2,
  197. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  198. constexpr bool operator==(const span_iterator<Type2>& rhs) const noexcept
  199. {
  200. Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
  201. return current_ == rhs.current_;
  202. }
  203. template <
  204. class Type2,
  205. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  206. constexpr bool operator!=(const span_iterator<Type2>& rhs) const noexcept
  207. {
  208. return !(*this == rhs);
  209. }
  210. template <
  211. class Type2,
  212. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  213. constexpr bool operator<(const span_iterator<Type2>& rhs) const noexcept
  214. {
  215. Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
  216. return current_ < rhs.current_;
  217. }
  218. template <
  219. class Type2,
  220. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  221. constexpr bool operator>(const span_iterator<Type2>& rhs) const noexcept
  222. {
  223. return rhs < *this;
  224. }
  225. template <
  226. class Type2,
  227. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  228. constexpr bool operator<=(const span_iterator<Type2>& rhs) const noexcept
  229. {
  230. return !(rhs < *this);
  231. }
  232. template <
  233. class Type2,
  234. std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
  235. constexpr bool operator>=(const span_iterator<Type2>& rhs) const noexcept
  236. {
  237. return !(*this < rhs);
  238. }
  239. #ifdef _MSC_VER
  240. // MSVC++ iterator debugging support; allows STL algorithms in 15.8+
  241. // to unwrap span_iterator to a pointer type after a range check in STL
  242. // algorithm calls
  243. friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept
  244. { // test that [lhs, rhs) forms a valid range inside an STL algorithm
  245. Expects(lhs.begin_ == rhs.begin_ // range spans have to match
  246. && lhs.end_ == rhs.end_ &&
  247. lhs.current_ <= rhs.current_); // range must not be transposed
  248. }
  249. constexpr void _Verify_offset(const difference_type n) const noexcept
  250. { // test that *this + n is within the range of this call
  251. if (n != 0) Expects(begin_ && current_ && end_);
  252. if (n > 0) Expects(end_ - current_ >= n);
  253. if (n < 0) Expects(current_ - begin_ >= -n);
  254. }
  255. // clang-format off
  256. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  257. // clang-format on
  258. constexpr pointer _Unwrapped() const noexcept
  259. { // after seeking *this to a high water mark, or using one of the
  260. // _Verify_xxx functions above, unwrap this span_iterator to a raw
  261. // pointer
  262. return current_;
  263. }
  264. // Tell the STL that span_iterator should not be unwrapped if it can't
  265. // validate in advance, even in release / optimized builds:
  266. #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
  267. static constexpr const bool _Unwrap_when_unverified = false;
  268. #else
  269. static constexpr bool _Unwrap_when_unverified = false;
  270. #endif
  271. // clang-format off
  272. GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive
  273. // clang-format on
  274. constexpr void _Seek_to(const pointer p) noexcept
  275. { // adjust the position of *this to previously verified location p
  276. // after _Unwrapped
  277. current_ = p;
  278. }
  279. #endif
  280. pointer begin_ = nullptr;
  281. pointer end_ = nullptr;
  282. pointer current_ = nullptr;
  283. };
  284. template <std::size_t Ext>
  285. class extent_type
  286. {
  287. public:
  288. using size_type = std::size_t;
  289. constexpr extent_type() noexcept = default;
  290. constexpr explicit extent_type(extent_type<dynamic_extent>);
  291. constexpr explicit extent_type(size_type size) { Expects(size == Ext); }
  292. constexpr size_type size() const noexcept { return Ext; }
  293. private:
  294. #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
  295. static constexpr const size_type size_ = Ext; // static size equal to Ext
  296. #else
  297. static constexpr size_type size_ = Ext; // static size equal to Ext
  298. #endif
  299. };
  300. template <>
  301. class extent_type<dynamic_extent>
  302. {
  303. public:
  304. using size_type = std::size_t;
  305. template <size_type Other>
  306. constexpr explicit extent_type(extent_type<Other> ext) : size_(ext.size())
  307. {}
  308. constexpr explicit extent_type(size_type size) : size_(size)
  309. {
  310. Expects(size != dynamic_extent);
  311. }
  312. constexpr size_type size() const noexcept { return size_; }
  313. private:
  314. size_type size_;
  315. };
  316. template <std::size_t Ext>
  317. constexpr extent_type<Ext>::extent_type(extent_type<dynamic_extent> ext)
  318. {
  319. Expects(ext.size() == Ext);
  320. }
  321. template <class ElementType, std::size_t Extent, std::size_t Offset, std::size_t Count>
  322. struct calculate_subspan_type
  323. {
  324. using type = span<ElementType, Count != dynamic_extent
  325. ? Count
  326. : (Extent != dynamic_extent ? Extent - Offset : Extent)>;
  327. };
  328. } // namespace details
  329. // [span], class template span
  330. template <class ElementType, std::size_t Extent>
  331. class span
  332. {
  333. public:
  334. // constants and types
  335. using element_type = ElementType;
  336. using value_type = std::remove_cv_t<ElementType>;
  337. using size_type = std::size_t;
  338. using pointer = element_type*;
  339. using const_pointer = const element_type*;
  340. using reference = element_type&;
  341. using const_reference = const element_type&;
  342. using difference_type = std::ptrdiff_t;
  343. using iterator = details::span_iterator<ElementType>;
  344. using reverse_iterator = std::reverse_iterator<iterator>;
  345. #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
  346. static constexpr const size_type extent{Extent};
  347. #else
  348. static constexpr size_type extent{Extent};
  349. #endif
  350. // [span.cons], span constructors, copy, assignment, and destructor
  351. template <bool Dependent = false,
  352. // "Dependent" is needed to make "std::enable_if_t<Dependent || Extent == 0 || Extent
  353. // == dynamic_extent>" SFINAE, since "std::enable_if_t<Extent == 0 || Extent ==
  354. // dynamic_extent>" is ill-formed when Extent is greater than 0.
  355. class = std::enable_if_t<(Dependent ||
  356. details::is_allowed_extent_conversion<0, Extent>::value)>>
  357. constexpr span() noexcept : storage_(nullptr, details::extent_type<0>())
  358. {}
  359. template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != gsl::dynamic_extent, int> = 0>
  360. constexpr explicit span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
  361. {
  362. Expects(count == Extent);
  363. }
  364. template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == gsl::dynamic_extent, int> = 0>
  365. constexpr span(pointer ptr, size_type count) noexcept : storage_(ptr, count)
  366. {}
  367. template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent != gsl::dynamic_extent, int> = 0>
  368. constexpr explicit span(pointer firstElem, pointer lastElem) noexcept
  369. : storage_(firstElem, static_cast<std::size_t>(lastElem - firstElem))
  370. {
  371. Expects(lastElem - firstElem == static_cast<difference_type>(Extent));
  372. }
  373. template <std::size_t MyExtent = Extent, std::enable_if_t<MyExtent == gsl::dynamic_extent, int> = 0>
  374. constexpr span(pointer firstElem, pointer lastElem) noexcept
  375. : storage_(firstElem, static_cast<std::size_t>(lastElem - firstElem))
  376. {}
  377. template <std::size_t N,
  378. std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0>
  379. constexpr span(element_type (&arr)[N]) noexcept
  380. : storage_(KnownNotNull{arr + 0}, details::extent_type<N>())
  381. {}
  382. template <
  383. class T, std::size_t N,
  384. std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value &&
  385. details::is_allowed_element_type_conversion<T, element_type>::value),
  386. int> = 0>
  387. constexpr span(std::array<T, N>& arr) noexcept
  388. : storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
  389. {}
  390. template <class T, std::size_t N,
  391. std::enable_if_t<
  392. (details::is_allowed_extent_conversion<N, Extent>::value &&
  393. details::is_allowed_element_type_conversion<const T, element_type>::value),
  394. int> = 0>
  395. constexpr span(const std::array<T, N>& arr) noexcept
  396. : storage_(KnownNotNull{arr.data()}, details::extent_type<N>())
  397. {}
  398. // NB: the SFINAE on these constructors uses .data() as an incomplete/imperfect proxy for the
  399. // requirement on Container to be a contiguous sequence container.
  400. template <std::size_t MyExtent = Extent, class Container,
  401. std::enable_if_t<
  402. MyExtent != dynamic_extent &&
  403. !details::is_span<Container>::value && !details::is_std_array<Container>::value &&
  404. std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
  405. std::is_convertible<
  406. std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
  407. element_type (*)[]>::value, int> = 0>
  408. constexpr explicit span(Container& cont) noexcept : span(cont.data(), cont.size())
  409. {}
  410. template <std::size_t MyExtent = Extent, class Container,
  411. std::enable_if_t<
  412. MyExtent == dynamic_extent &&
  413. !details::is_span<Container>::value && !details::is_std_array<Container>::value &&
  414. std::is_pointer<decltype(std::declval<Container&>().data())>::value &&
  415. std::is_convertible<
  416. std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[],
  417. element_type (*)[]>::value, int> = 0>
  418. constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
  419. {}
  420. template <std::size_t MyExtent = Extent, class Container,
  421. std::enable_if_t<
  422. MyExtent != dynamic_extent &&
  423. std::is_const<element_type>::value && !details::is_span<Container>::value &&
  424. !details::is_std_array<Container>::value &&
  425. std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
  426. std::is_convertible<std::remove_pointer_t<
  427. decltype(std::declval<const Container&>().data())> (*)[],
  428. element_type (*)[]>::value, int> = 0>
  429. constexpr explicit span(const Container& cont) noexcept : span(cont.data(), cont.size())
  430. {}
  431. template <std::size_t MyExtent = Extent, class Container,
  432. std::enable_if_t<
  433. MyExtent == dynamic_extent &&
  434. std::is_const<element_type>::value && !details::is_span<Container>::value &&
  435. !details::is_std_array<Container>::value &&
  436. std::is_pointer<decltype(std::declval<const Container&>().data())>::value &&
  437. std::is_convertible<std::remove_pointer_t<
  438. decltype(std::declval<const Container&>().data())> (*)[],
  439. element_type (*)[]>::value, int> = 0>
  440. constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size())
  441. {}
  442. constexpr span(const span& other) noexcept = default;
  443. template <
  444. class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
  445. std::enable_if_t<
  446. (MyExtent == dynamic_extent || MyExtent == OtherExtent) &&
  447. details::is_allowed_element_type_conversion<OtherElementType, element_type>::value, int> = 0>
  448. constexpr span(const span<OtherElementType, OtherExtent>& other) noexcept
  449. : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
  450. {}
  451. template <
  452. class OtherElementType, std::size_t OtherExtent, std::size_t MyExtent = Extent,
  453. std::enable_if_t<
  454. MyExtent != dynamic_extent && OtherExtent == dynamic_extent &&
  455. details::is_allowed_element_type_conversion<OtherElementType, element_type>::value, int> = 0>
  456. constexpr explicit span(const span<OtherElementType, OtherExtent>& other) noexcept
  457. : storage_(other.data(), details::extent_type<OtherExtent>(other.size()))
  458. {}
  459. ~span() noexcept = default;
  460. constexpr span& operator=(const span& other) noexcept = default;
  461. // [span.sub], span subviews
  462. template <std::size_t Count>
  463. constexpr span<element_type, Count> first() const noexcept
  464. {
  465. Expects(Count <= size());
  466. return span<element_type, Count>{data(), Count};
  467. }
  468. template <std::size_t Count>
  469. // clang-format off
  470. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  471. // clang-format on
  472. constexpr span<element_type, Count> last() const noexcept
  473. {
  474. Expects(Count <= size());
  475. return span<element_type, Count>{data() + (size() - Count), Count};
  476. }
  477. template <std::size_t Offset, std::size_t Count = dynamic_extent>
  478. // clang-format off
  479. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  480. // clang-format on
  481. constexpr auto subspan() const noexcept ->
  482. typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type
  483. {
  484. Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset)));
  485. using type = typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type;
  486. return type{data() + Offset, Count == dynamic_extent ? size() - Offset : Count};
  487. }
  488. constexpr span<element_type, dynamic_extent> first(size_type count) const noexcept
  489. {
  490. Expects(count <= size());
  491. return {data(), count};
  492. }
  493. constexpr span<element_type, dynamic_extent> last(size_type count) const noexcept
  494. {
  495. Expects(count <= size());
  496. return make_subspan(size() - count, dynamic_extent, subspan_selector<Extent>{});
  497. }
  498. constexpr span<element_type, dynamic_extent> subspan(size_type offset,
  499. size_type count = dynamic_extent) const
  500. noexcept
  501. {
  502. return make_subspan(offset, count, subspan_selector<Extent>{});
  503. }
  504. // [span.obs], span observers
  505. constexpr size_type size() const noexcept { return storage_.size(); }
  506. constexpr size_type size_bytes() const noexcept
  507. {
  508. Expects(size() < dynamic_extent / sizeof(element_type));
  509. return size() * sizeof(element_type);
  510. }
  511. constexpr bool empty() const noexcept { return size() == 0; }
  512. // [span.elem], span element access
  513. // clang-format off
  514. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  515. // clang-format on
  516. constexpr reference operator[](size_type idx) const noexcept
  517. {
  518. Expects(idx < size());
  519. return data()[idx];
  520. }
  521. constexpr reference front() const noexcept
  522. {
  523. Expects(size() > 0);
  524. return data()[0];
  525. }
  526. constexpr reference back() const noexcept
  527. {
  528. Expects(size() > 0);
  529. return data()[size() - 1];
  530. }
  531. constexpr pointer data() const noexcept { return storage_.data(); }
  532. // [span.iter], span iterator support
  533. constexpr iterator begin() const noexcept
  534. {
  535. const auto data = storage_.data();
  536. // clang-format off
  537. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  538. // clang-format on
  539. return {data, data + size(), data};
  540. }
  541. constexpr iterator end() const noexcept
  542. {
  543. const auto data = storage_.data();
  544. // clang-format off
  545. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  546. // clang-format on
  547. const auto endData = data + storage_.size();
  548. return {data, endData, endData};
  549. }
  550. constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; }
  551. constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; }
  552. #ifdef _MSC_VER
  553. // Tell MSVC how to unwrap spans in range-based-for
  554. constexpr pointer _Unchecked_begin() const noexcept { return data(); }
  555. constexpr pointer _Unchecked_end() const noexcept
  556. {
  557. // clang-format off
  558. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  559. // clang-format on
  560. return data() + size();
  561. }
  562. #endif // _MSC_VER
  563. private:
  564. // Needed to remove unnecessary null check in subspans
  565. struct KnownNotNull
  566. {
  567. pointer p;
  568. };
  569. // this implementation detail class lets us take advantage of the
  570. // empty base class optimization to pay for only storage of a single
  571. // pointer in the case of fixed-size spans
  572. template <class ExtentType>
  573. class storage_type : public ExtentType
  574. {
  575. public:
  576. // KnownNotNull parameter is needed to remove unnecessary null check
  577. // in subspans and constructors from arrays
  578. template <class OtherExtentType>
  579. constexpr storage_type(KnownNotNull data, OtherExtentType ext)
  580. : ExtentType(ext), data_(data.p)
  581. {
  582. Expects(ExtentType::size() != dynamic_extent);
  583. }
  584. template <class OtherExtentType>
  585. constexpr storage_type(pointer data, OtherExtentType ext) : ExtentType(ext), data_(data)
  586. {
  587. Expects(ExtentType::size() != dynamic_extent);
  588. Expects(data || ExtentType::size() == 0);
  589. }
  590. constexpr pointer data() const noexcept { return data_; }
  591. private:
  592. pointer data_;
  593. };
  594. storage_type<details::extent_type<Extent>> storage_;
  595. // The rest is needed to remove unnecessary null check
  596. // in subspans and constructors from arrays
  597. constexpr span(KnownNotNull ptr, size_type count) noexcept : storage_(ptr, count) {}
  598. template <std::size_t CallerExtent>
  599. class subspan_selector
  600. {
  601. };
  602. template <std::size_t CallerExtent>
  603. constexpr span<element_type, dynamic_extent> make_subspan(size_type offset, size_type count,
  604. subspan_selector<CallerExtent>) const
  605. noexcept
  606. {
  607. const span<element_type, dynamic_extent> tmp(*this);
  608. return tmp.subspan(offset, count);
  609. }
  610. // clang-format off
  611. GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
  612. // clang-format on
  613. constexpr span<element_type, dynamic_extent>
  614. make_subspan(size_type offset, size_type count, subspan_selector<dynamic_extent>) const noexcept
  615. {
  616. Expects(size() >= offset);
  617. if (count == dynamic_extent) { return {KnownNotNull{data() + offset}, size() - offset}; }
  618. Expects(size() - offset >= count);
  619. return {KnownNotNull{data() + offset}, count};
  620. }
  621. };
  622. #if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
  623. // Deduction Guides
  624. template <class Type, std::size_t Extent>
  625. span(Type (&)[Extent])->span<Type, Extent>;
  626. template <class Type, std::size_t Size>
  627. span(std::array<Type, Size>&)->span<Type, Size>;
  628. template <class Type, std::size_t Size>
  629. span(const std::array<Type, Size>&)->span<const Type, Size>;
  630. template <class Container,
  631. class Element = std::remove_pointer_t<decltype(std::declval<Container&>().data())>>
  632. span(Container&)->span<Element>;
  633. template <class Container,
  634. class Element = std::remove_pointer_t<decltype(std::declval<const Container&>().data())>>
  635. span(const Container&)->span<Element>;
  636. #endif // ( defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L) )
  637. #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND)
  638. template <class ElementType, std::size_t Extent>
  639. constexpr const typename span<ElementType, Extent>::size_type span<ElementType, Extent>::extent;
  640. #endif
  641. namespace details
  642. {
  643. // if we only supported compilers with good constexpr support then
  644. // this pair of classes could collapse down to a constexpr function
  645. // we should use a narrow_cast<> to go to std::size_t, but older compilers may not see it as
  646. // constexpr
  647. // and so will fail compilation of the template
  648. template <class ElementType, std::size_t Extent>
  649. struct calculate_byte_size : std::integral_constant<std::size_t, sizeof(ElementType) * Extent>
  650. {
  651. static_assert(Extent < dynamic_extent / sizeof(ElementType), "Size is too big.");
  652. };
  653. template <class ElementType>
  654. struct calculate_byte_size<ElementType, dynamic_extent>
  655. : std::integral_constant<std::size_t, dynamic_extent>
  656. {
  657. };
  658. } // namespace details
  659. // [span.objectrep], views of object representation
  660. template <class ElementType, std::size_t Extent>
  661. span<const byte, details::calculate_byte_size<ElementType, Extent>::value>
  662. as_bytes(span<ElementType, Extent> s) noexcept
  663. {
  664. using type = span<const byte, details::calculate_byte_size<ElementType, Extent>::value>;
  665. // clang-format off
  666. GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
  667. // clang-format on
  668. return type{reinterpret_cast<const byte*>(s.data()), s.size_bytes()};
  669. }
  670. template <class ElementType, std::size_t Extent,
  671. std::enable_if_t<!std::is_const<ElementType>::value, int> = 0>
  672. span<byte, details::calculate_byte_size<ElementType, Extent>::value>
  673. as_writable_bytes(span<ElementType, Extent> s) noexcept
  674. {
  675. using type = span<byte, details::calculate_byte_size<ElementType, Extent>::value>;
  676. // clang-format off
  677. GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
  678. // clang-format on
  679. return type{reinterpret_cast<byte*>(s.data()), s.size_bytes()};
  680. }
  681. } // namespace gsl
  682. #if defined(_MSC_VER) && !defined(__clang__)
  683. #pragma warning(pop)
  684. #endif // _MSC_VER
  685. #if defined(__GNUC__) && __GNUC__ > 6
  686. #pragma GCC diagnostic pop
  687. #endif // __GNUC__ > 6
  688. #endif // GSL_SPAN_H