1// Components for manipulating non-owning sequences of objects -*- C++ -*-
 
    3// Copyright (C) 2019-2021 Free Software Foundation, Inc.
 
    5// This file is part of the GNU ISO C++ Library.  This library is free
 
    6// software; you can redistribute it and/or modify it under the
 
    7// terms of the GNU General Public License as published by the
 
    8// Free Software Foundation; either version 3, or (at your option)
 
   11// This library is distributed in the hope that it will be useful,
 
   12// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
   13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
   14// GNU General Public License for more details.
 
   16// Under Section 7 of GPL version 3, you are granted additional
 
   17// permissions described in the GCC Runtime Library Exception, version
 
   18// 3.1, as published by the Free Software Foundation.
 
   20// You should have received a copy of the GNU General Public License and
 
   21// a copy of the GCC Runtime Library Exception along with this program;
 
   22// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
   23// <http://www.gnu.org/licenses/>.
 
   26 *  This is a Standard C++ Library header.
 
   31// Contributed by ThePhD
 
   35#define _GLIBCXX_SPAN 1
 
   37#pragma GCC system_header
 
   39#if __cplusplus > 201703L
 
   43#include <bits/stl_iterator.h>
 
   44#include <bits/ranges_base.h>
 
   47namespace std _GLIBCXX_VISIBILITY(default)
 
   49_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   51#define __cpp_lib_span 202002L
 
   53  inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
 
   55  template<typename _Type, size_t _Extent>
 
   60    template<typename _Tp>
 
   61      struct __is_std_span : false_type { };
 
   63    template<typename _Tp, size_t _Num>
 
   64      struct __is_std_span<span<_Tp, _Num>> : true_type { };
 
   66    template<typename _Tp>
 
   67      struct __is_std_array : false_type { };
 
   69    template<typename _Tp, size_t _Num>
 
   70      struct __is_std_array<std::array<_Tp, _Num>> : true_type { };
 
   72    template<size_t _Extent>
 
   73      class __extent_storage
 
   77        __extent_storage(size_t) noexcept
 
   80        static constexpr size_t
 
   86      class __extent_storage<dynamic_extent>
 
   90        __extent_storage(size_t __extent) noexcept
 
   91        : _M_extent_value(__extent)
 
   95        _M_extent() const noexcept
 
   96        { return this->_M_extent_value; }
 
   99        size_t _M_extent_value;
 
  101  } // namespace __detail
 
  103  template<typename _Type, size_t _Extent = dynamic_extent>
 
  106      template<size_t _Offset, size_t _Count>
 
  107        static constexpr size_t
 
  110          if constexpr (_Count != dynamic_extent)
 
  112          else if constexpr (extent != dynamic_extent)
 
  113            return _Extent - _Offset;
 
  115            return dynamic_extent;
 
  118      // _GLIBCXX_RESOLVE_LIB_DEFECTS
 
  119      // 3255. span's array constructor is too strict
 
  120      template<typename _Tp, size_t _ArrayExtent>
 
  121        requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
 
  122        using __is_compatible_array = __is_array_convertible<_Type, _Tp>;
 
  124      template<typename _Ref>
 
  125        using __is_compatible_ref
 
  126          = __is_array_convertible<_Type, remove_reference_t<_Ref>>;
 
  130      using element_type           = _Type;
 
  131      using value_type             = remove_cv_t<_Type>;
 
  132      using size_type              = size_t;
 
  133      using difference_type        = ptrdiff_t;
 
  134      using pointer                = _Type*;
 
  135      using const_pointer          = const _Type*;
 
  136      using reference              = element_type&;
 
  137      using const_reference        = const element_type&;
 
  138      using iterator = __gnu_cxx::__normal_iterator<pointer, span>;
 
  139      using reverse_iterator       = std::reverse_iterator<iterator>;
 
  142      static constexpr size_t extent = _Extent;
 
  144      // constructors, copy and assignment
 
  148      requires ((_Extent + 1u) <= 1u)
 
  149      : _M_ptr(nullptr), _M_extent(0)
 
  152      template<contiguous_iterator _It>
 
  153        requires __is_compatible_ref<iter_reference_t<_It>>::value
 
  154        constexpr explicit(extent != dynamic_extent)
 
  155        span(_It __first, size_type __count)
 
  157        : _M_ptr(std::to_address(__first)), _M_extent(__count)
 
  159          if constexpr (_Extent != dynamic_extent)
 
  161              __glibcxx_assert(__count == _Extent);
 
  163          __glibcxx_requires_valid_range(__first, __first + __count);
 
  166      template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
 
  167        requires __is_compatible_ref<iter_reference_t<_It>>::value
 
  168          && (!is_convertible_v<_End, size_type>)
 
  169        constexpr explicit(extent != dynamic_extent)
 
  170        span(_It __first, _End __last)
 
  171        noexcept(noexcept(__last - __first))
 
  172        : _M_ptr(std::to_address(__first)),
 
  173          _M_extent(static_cast<size_type>(__last - __first))
 
  175          if constexpr (_Extent != dynamic_extent)
 
  177              __glibcxx_assert((__last - __first) == _Extent);
 
  179          __glibcxx_requires_valid_range(__first, __last);
 
  182      template<size_t _ArrayExtent>
 
  183        requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
 
  185        span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
 
  186        : span(static_cast<pointer>(__arr), _ArrayExtent)
 
  189      template<typename _Tp, size_t _ArrayExtent>
 
  190        requires __is_compatible_array<_Tp, _ArrayExtent>::value
 
  192        span(array<_Tp, _ArrayExtent>& __arr) noexcept
 
  193        : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
 
  196      template<typename _Tp, size_t _ArrayExtent>
 
  197        requires __is_compatible_array<const _Tp, _ArrayExtent>::value
 
  199        span(const array<_Tp, _ArrayExtent>& __arr) noexcept
 
  200        : span(static_cast<pointer>(__arr.data()), _ArrayExtent)
 
  203      template<typename _Range>
 
  204        requires (!__detail::__is_std_span<remove_cvref_t<_Range>>::value)
 
  205          && (!__detail::__is_std_array<remove_cvref_t<_Range>>::value)
 
  206          && (!is_array_v<remove_cvref_t<_Range>>)
 
  207          && ranges::contiguous_range<_Range> && ranges::sized_range<_Range>
 
  208          && (ranges::borrowed_range<_Range> || is_const_v<element_type>)
 
  209          && __is_compatible_ref<ranges::range_reference_t<_Range>>::value
 
  210        constexpr explicit(extent != dynamic_extent)
 
  211        span(_Range&& __range)
 
  212        noexcept(noexcept(ranges::data(__range))
 
  213                  && noexcept(ranges::size(__range)))
 
  214        : span(ranges::data(__range), ranges::size(__range))
 
  216          if constexpr (extent != dynamic_extent)
 
  218              __glibcxx_assert(ranges::size(__range) == extent);
 
  223      span(const span&) noexcept = default;
 
  225      template<typename _OType, size_t _OExtent>
 
  226        requires (_Extent == dynamic_extent || _OExtent == dynamic_extent
 
  227                  || _Extent == _OExtent)
 
  228          && (__is_array_convertible<_Type, _OType>::value)
 
  230        explicit(extent != dynamic_extent && _OExtent == dynamic_extent)
 
  231        span(const span<_OType, _OExtent>& __s) noexcept
 
  232        : _M_extent(__s.size()), _M_ptr(__s.data())
 
  234          if constexpr (extent != dynamic_extent)
 
  236              __glibcxx_assert(__s.size() == extent);
 
  240      ~span() noexcept = default;
 
  243      operator=(const span&) noexcept = default;
 
  248      size() const noexcept
 
  249      { return this->_M_extent._M_extent(); }
 
  252      size_bytes() const noexcept
 
  253      { return this->_M_extent._M_extent() * sizeof(element_type); }
 
  255      [[nodiscard]] constexpr bool
 
  256      empty() const noexcept
 
  257      { return size() == 0; }
 
  262      front() const noexcept
 
  264        __glibcxx_assert(!empty());
 
  265        return *this->_M_ptr;
 
  269      back() const noexcept
 
  271        __glibcxx_assert(!empty());
 
  272        return *(this->_M_ptr + (size() - 1));
 
  276      operator[](size_type __idx) const noexcept
 
  278        __glibcxx_assert(__idx < size());
 
  279        return *(this->_M_ptr + __idx);
 
  283      data() const noexcept
 
  284      { return this->_M_ptr; }
 
  289      begin() const noexcept
 
  290      { return iterator(this->_M_ptr); }
 
  294      { return iterator(this->_M_ptr + this->size()); }
 
  296      constexpr reverse_iterator
 
  297      rbegin() const noexcept
 
  298      { return reverse_iterator(this->end()); }
 
  300      constexpr reverse_iterator
 
  301      rend() const noexcept
 
  302      { return reverse_iterator(this->begin()); }
 
  306      template<size_t _Count>
 
  307        constexpr span<element_type, _Count>
 
  308        first() const noexcept
 
  310          if constexpr (_Extent == dynamic_extent)
 
  311            __glibcxx_assert(_Count <= size());
 
  313            static_assert(_Count <= extent);
 
  314          using _Sp = span<element_type, _Count>;
 
  315          return _Sp{ this->data(), _Count };
 
  318      constexpr span<element_type, dynamic_extent>
 
  319      first(size_type __count) const noexcept
 
  321        __glibcxx_assert(__count <= size());
 
  322        return { this->data(), __count };
 
  325      template<size_t _Count>
 
  326        constexpr span<element_type, _Count>
 
  327        last() const noexcept
 
  329          if constexpr (_Extent == dynamic_extent)
 
  330            __glibcxx_assert(_Count <= size());
 
  332            static_assert(_Count <= extent);
 
  333          using _Sp = span<element_type, _Count>;
 
  334          return _Sp{ this->data() + (this->size() - _Count), _Count };
 
  337      constexpr span<element_type, dynamic_extent>
 
  338      last(size_type __count) const noexcept
 
  340        __glibcxx_assert(__count <= size());
 
  341        return { this->data() + (this->size() - __count), __count };
 
  344      template<size_t _Offset, size_t _Count = dynamic_extent>
 
  346        subspan() const noexcept
 
  347        -> span<element_type, _S_subspan_extent<_Offset, _Count>()>
 
  349          if constexpr (_Extent == dynamic_extent)
 
  351              __glibcxx_assert(_Offset <= size());
 
  354            static_assert(_Offset <= extent);
 
  356          using _Sp = span<element_type, _S_subspan_extent<_Offset, _Count>()>;
 
  358          if constexpr (_Count == dynamic_extent)
 
  359            return _Sp{ this->data() + _Offset, this->size() - _Offset };
 
  362              if constexpr (_Extent == dynamic_extent)
 
  364                  __glibcxx_assert(_Count <= size());
 
  365                  __glibcxx_assert(_Count <= (size() - _Offset));
 
  369                  static_assert(_Count <= extent);
 
  370                  static_assert(_Count <= (extent - _Offset));
 
  372              return _Sp{ this->data() + _Offset, _Count };
 
  376      constexpr span<element_type, dynamic_extent>
 
  377      subspan(size_type __offset, size_type __count = dynamic_extent) const
 
  380        __glibcxx_assert(__offset <= size());
 
  381        if (__count == dynamic_extent)
 
  382          __count = this->size() - __offset;
 
  385            __glibcxx_assert(__count <= size());
 
  386            __glibcxx_assert(__offset + __count <= size());
 
  388        return {this->data() + __offset, __count};
 
  393      [[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
 
  398  template<typename _Type, size_t _ArrayExtent>
 
  399    span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>;
 
  401  template<typename _Type, size_t _ArrayExtent>
 
  402    span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>;
 
  404  template<typename _Type, size_t _ArrayExtent>
 
  405    span(const array<_Type, _ArrayExtent>&)
 
  406      -> span<const _Type, _ArrayExtent>;
 
  408  template<contiguous_iterator _Iter, typename _End>
 
  410      -> span<remove_reference_t<iter_reference_t<_Iter>>>;
 
  412  template<ranges::contiguous_range _Range>
 
  414      -> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
 
  416  template<typename _Type, size_t _Extent>
 
  418    span<const byte, _Extent == dynamic_extent
 
  419        ? dynamic_extent : _Extent * sizeof(_Type)>
 
  420    as_bytes(span<_Type, _Extent> __sp) noexcept
 
  422      auto data = reinterpret_cast<const byte*>(__sp.data());
 
  423      auto size = __sp.size_bytes();
 
  424      constexpr auto extent = _Extent == dynamic_extent
 
  425        ? dynamic_extent : _Extent * sizeof(_Type);
 
  426      return span<const byte, extent>{data, size};
 
  429  template<typename _Type, size_t _Extent>
 
  430    requires (!is_const_v<_Type>)
 
  432    span<byte, _Extent == dynamic_extent
 
  433       ? dynamic_extent : _Extent * sizeof(_Type)>
 
  434    as_writable_bytes(span<_Type, _Extent> __sp) noexcept
 
  436      auto data = reinterpret_cast<byte*>(__sp.data());
 
  437      auto size = __sp.size_bytes();
 
  438      constexpr auto extent = _Extent == dynamic_extent
 
  439        ? dynamic_extent : _Extent * sizeof(_Type);
 
  440      return span<byte, extent>{data, size};
 
  445    // Opt-in to borrowed_range concept
 
  446    template<typename _ElementType, size_t _Extent>
 
  447      inline constexpr bool
 
  448        enable_borrowed_range<span<_ElementType, _Extent>> = true;
 
  450    // Opt-in to view concept
 
  451    template<typename _ElementType, size_t _Extent>
 
  452      inline constexpr bool
 
  453        enable_view<span<_ElementType, _Extent>> = true;
 
  455_GLIBCXX_END_NAMESPACE_VERSION
 
  459#endif // _GLIBCXX_SPAN