class __extent_storage
{
public:
+ // Used for runtime sizes that must satisfy the precondition.
constexpr
- __extent_storage(size_t) noexcept
+ __extent_storage([[maybe_unused]] size_t __n) noexcept
+ { __glibcxx_assert(__n == _Extent); }
+
+ // Used for constant sizes that are already known to be correct.
+ consteval
+ __extent_storage(integral_constant<size_t, _Extent>) noexcept
{ }
+ // "I've made a huge mistake" - George Oscar Bluth II
+ template<size_t _Gob>
+ __extent_storage(integral_constant<size_t, _Gob>) = delete;
+
+ [[__gnu__::__always_inline__]]
static constexpr size_t
_M_extent() noexcept
{ return _Extent; }
class __extent_storage<dynamic_extent>
{
public:
+ [[__gnu__::__always_inline__]]
constexpr
__extent_storage(size_t __extent) noexcept
: _M_extent_value(__extent)
{ }
+ [[__gnu__::__always_inline__]]
constexpr size_t
_M_extent() const noexcept
{ return this->_M_extent_value; }
private:
size_t _M_extent_value;
};
+
+ template<typename _Type> struct __span_ptr { _Type* const _M_ptr; };
+
} // namespace __detail
template<typename _Type, size_t _Extent = dynamic_extent>
// Nested type so that _Type is not an associated class of iterator.
struct __iter_tag;
+ template<size_t _Nm>
+ static inline constexpr integral_constant<size_t, _Nm> __v{};
+
public:
// member types
using element_type = _Type;
constexpr
span() noexcept
requires (_Extent == dynamic_extent || _Extent == 0)
- : _M_ptr(nullptr), _M_extent(0)
+ : _M_ptr(nullptr), _M_extent(__v<0>)
{ }
template<contiguous_iterator _It>
span(_It __first, size_type __count)
noexcept
: _M_ptr(std::to_address(__first)), _M_extent(__count)
- {
- if constexpr (_Extent != dynamic_extent)
- {
- __glibcxx_assert(__count == _Extent);
- }
- __glibcxx_requires_valid_range(__first, __first + __count);
- }
+ { __glibcxx_requires_valid_range(__first, __first + __count); }
template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
requires __is_compatible_ref<iter_reference_t<_It>>::value
noexcept(noexcept(__last - __first))
: _M_ptr(std::to_address(__first)),
_M_extent(static_cast<size_type>(__last - __first))
- {
- if constexpr (_Extent != dynamic_extent)
- {
- __glibcxx_assert((__last - __first) == _Extent);
- }
- __glibcxx_requires_valid_range(__first, __last);
- }
+ { __glibcxx_requires_valid_range(__first, __last); }
template<size_t _ArrayExtent>
requires (_Extent == dynamic_extent || _ArrayExtent == _Extent)
constexpr
span(type_identity_t<element_type> (&__arr)[_ArrayExtent]) noexcept
- : _M_ptr(__arr), _M_extent(_ArrayExtent)
+ : _M_ptr(__arr), _M_extent(__v<_ArrayExtent>)
{ }
template<typename _Tp, size_t _ArrayExtent>
requires __is_compatible_array<_Tp, _ArrayExtent>::value
constexpr
span(array<_Tp, _ArrayExtent>& __arr) noexcept
- : _M_ptr(__arr.data()), _M_extent(_ArrayExtent)
+ : _M_ptr(__arr.data()), _M_extent(__v<_ArrayExtent>)
{ }
template<typename _Tp, size_t _ArrayExtent>
requires __is_compatible_array<const _Tp, _ArrayExtent>::value
constexpr
span(const array<_Tp, _ArrayExtent>& __arr) noexcept
- : _M_ptr(__arr.data()), _M_extent(_ArrayExtent)
+ : _M_ptr(__arr.data()), _M_extent(__v<_ArrayExtent>)
{ }
template<typename _Range>
noexcept(noexcept(ranges::data(__range))
&& noexcept(ranges::size(__range)))
: _M_ptr(ranges::data(__range)), _M_extent(ranges::size(__range))
- {
- if constexpr (extent != dynamic_extent)
- {
- __glibcxx_assert(ranges::size(__range) == extent);
- }
- }
+ { }
constexpr
span(const span&) noexcept = default;
explicit(extent != dynamic_extent && _OExtent == dynamic_extent)
span(const span<_OType, _OExtent>& __s) noexcept
: _M_ptr(__s.data()), _M_extent(__s.size())
- {
- if constexpr (extent != dynamic_extent)
- {
- __glibcxx_assert(__s.size() == extent);
- }
- }
+ { }
~span() noexcept = default;
else
static_assert(_Count <= extent);
using _Sp = span<element_type, _Count>;
- return _Sp{ this->data(), _Count };
+ return _Sp{ _SizedPtr{this->data()} };
}
[[nodiscard]]
else
static_assert(_Count <= extent);
using _Sp = span<element_type, _Count>;
- return _Sp{ this->data() + (this->size() - _Count), _Count };
+ return _Sp{ _SizedPtr{this->data() + (this->size() - _Count)} };
}
[[nodiscard]]
static_assert(_Count <= extent);
static_assert(_Count <= (extent - _Offset));
}
- return _Sp{ this->data() + _Offset, _Count };
+ return _Sp{ _SizedPtr{this->data() + _Offset} };
}
}
}
private:
+ template<typename, size_t> friend class span;
+
+ // Tag type for pointer that has known extent.
+ using _SizedPtr = __detail::__span_ptr<_Type>;
+
+ // Private constructor with an implied extent.
+ [[__gnu__::__always_inline__]]
+ constexpr explicit
+ span(_SizedPtr __ptr) noexcept
+ requires (extent != dynamic_extent)
+ : _M_ptr(__ptr._M_ptr), _M_extent(__v<extent>)
+ { }
+
pointer _M_ptr;
[[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
};