// Components for manipulating non-owning sequences of objects -*- C++ -*-
-// Copyright (C) 2019-2020 Free Software Foundation, Inc.
+// Copyright (C) 2019-2024 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
#pragma GCC system_header
-#if __cplusplus > 201703L
+#define __glibcxx_want_span
+#include <bits/version.h>
-#include <type_traits>
+#ifdef __cpp_lib_span // C++ >= 20 && concepts
#include <array>
+#include <cstddef>
#include <bits/stl_iterator.h>
#include <bits/ranges_base.h>
-
-#if __cpp_lib_concepts
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
-#define __cpp_lib_span 202002L
-
inline constexpr size_t dynamic_extent = static_cast<size_t>(-1);
template<typename _Type, size_t _Extent>
namespace __detail
{
template<typename _Tp>
- struct __is_std_span : false_type { };
+ inline constexpr bool __is_span = false;
template<typename _Tp, size_t _Num>
- struct __is_std_span<span<_Tp, _Num>> : true_type { };
+ inline constexpr bool __is_span<span<_Tp, _Num>> = true;
template<typename _Tp>
- struct __is_std_array : false_type { };
+ inline constexpr bool __is_std_array = false;
template<typename _Tp, size_t _Num>
- struct __is_std_array<_GLIBCXX_STD_C::array<_Tp, _Num>> : true_type { };
-
-#ifdef _GLIBCXX_DEBUG
- template<typename _Tp, size_t _Num>
- struct __is_std_array<__debug::array<_Tp, _Num>> : true_type { };
-#endif
+ inline constexpr bool __is_std_array<std::array<_Tp, _Num>> = true;
template<size_t _Extent>
class __extent_storage
using const_reference = const element_type&;
using iterator = __gnu_cxx::__normal_iterator<pointer, span>;
using reverse_iterator = std::reverse_iterator<iterator>;
+#if __cplusplus > 202002L
+ using const_iterator = std::const_iterator<iterator>;
+ using const_reverse_iterator = std::const_iterator<reverse_iterator>;
+#endif
// member constants
static constexpr size_t extent = _Extent;
constexpr
span() noexcept
- requires ((_Extent + 1u) <= 1u)
- : _M_extent(0), _M_ptr(nullptr)
+ requires (_Extent == dynamic_extent || _Extent == 0)
+ : _M_ptr(nullptr), _M_extent(0)
{ }
template<contiguous_iterator _It>
constexpr explicit(extent != dynamic_extent)
span(_It __first, size_type __count)
noexcept
- : _M_extent(__count), _M_ptr(std::to_address(__first))
+ : _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);
}
template<contiguous_iterator _It, sized_sentinel_for<_It> _End>
constexpr explicit(extent != dynamic_extent)
span(_It __first, _End __last)
noexcept(noexcept(__last - __first))
- : _M_extent(static_cast<size_type>(__last - __first)),
- _M_ptr(std::to_address(__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);
}
template<size_t _ArrayExtent>
{ }
template<typename _Range>
- requires ranges::contiguous_range<_Range> && ranges::sized_range<_Range>
- && (ranges::borrowed_range<_Range> || is_const_v<element_type>)
- && (!__detail::__is_std_span<remove_cvref_t<_Range>>::value)
- && (!__detail::__is_std_array<remove_cvref_t<_Range>>::value)
+ requires (!__detail::__is_span<remove_cvref_t<_Range>>)
+ && (!__detail::__is_std_array<remove_cvref_t<_Range>>)
&& (!is_array_v<remove_cvref_t<_Range>>)
+ && ranges::contiguous_range<_Range> && ranges::sized_range<_Range>
+ && (ranges::borrowed_range<_Range> || is_const_v<element_type>)
&& __is_compatible_ref<ranges::range_reference_t<_Range>>::value
constexpr explicit(extent != dynamic_extent)
span(_Range&& __range)
// observers
+ [[nodiscard]]
constexpr size_type
size() const noexcept
{ return this->_M_extent._M_extent(); }
+ [[nodiscard]]
constexpr size_type
size_bytes() const noexcept
{ return this->_M_extent._M_extent() * sizeof(element_type); }
- [[nodiscard]] constexpr bool
+ [[nodiscard]]
+ constexpr bool
empty() const noexcept
{ return size() == 0; }
// element access
+ [[nodiscard]]
constexpr reference
front() const noexcept
{
return *this->_M_ptr;
}
+ [[nodiscard]]
constexpr reference
back() const noexcept
{
return *(this->_M_ptr + (size() - 1));
}
+ [[nodiscard]]
constexpr reference
operator[](size_type __idx) const noexcept
{
return *(this->_M_ptr + __idx);
}
+ [[nodiscard]]
+ constexpr reference
+ at(size_type __idx) const
+ {
+ if (__idx >= size())
+ __throw_out_of_range_fmt(__N("span::at(%zu) out-of-range for span "
+ "of size %zu"), __idx, this->size());
+ return *(this->_M_ptr + __idx);
+ }
+
+ [[nodiscard]]
constexpr pointer
data() const noexcept
{ return this->_M_ptr; }
// iterator support
+ [[nodiscard]]
constexpr iterator
begin() const noexcept
{ return iterator(this->_M_ptr); }
+ [[nodiscard]]
constexpr iterator
end() const noexcept
{ return iterator(this->_M_ptr + this->size()); }
+ [[nodiscard]]
constexpr reverse_iterator
rbegin() const noexcept
{ return reverse_iterator(this->end()); }
+ [[nodiscard]]
constexpr reverse_iterator
rend() const noexcept
{ return reverse_iterator(this->begin()); }
+#if __cplusplus > 202002L
+ [[nodiscard]]
+ constexpr const_iterator
+ cbegin() const noexcept
+ { return begin(); }
+
+ [[nodiscard]]
+ constexpr const_iterator
+ cend() const noexcept
+ { return end(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crbegin() const noexcept
+ { return rbegin(); }
+
+ [[nodiscard]]
+ constexpr const_reverse_iterator
+ crend() const noexcept
+ { return rend(); }
+#endif
+
// subviews
template<size_t _Count>
+ [[nodiscard]]
constexpr span<element_type, _Count>
first() const noexcept
{
return _Sp{ this->data(), _Count };
}
+ [[nodiscard]]
constexpr span<element_type, dynamic_extent>
first(size_type __count) const noexcept
{
}
template<size_t _Count>
+ [[nodiscard]]
constexpr span<element_type, _Count>
last() const noexcept
{
return _Sp{ this->data() + (this->size() - _Count), _Count };
}
+ [[nodiscard]]
constexpr span<element_type, dynamic_extent>
last(size_type __count) const noexcept
{
}
template<size_t _Offset, size_t _Count = dynamic_extent>
+ [[nodiscard]]
constexpr auto
subspan() const noexcept
-> span<element_type, _S_subspan_extent<_Offset, _Count>()>
}
}
+ [[nodiscard]]
constexpr span<element_type, dynamic_extent>
subspan(size_type __offset, size_type __count = dynamic_extent) const
noexcept
}
private:
- [[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
pointer _M_ptr;
+ [[no_unique_address]] __detail::__extent_storage<extent> _M_extent;
};
// deduction guides
span(_Iter, _End)
-> span<remove_reference_t<iter_reference_t<_Iter>>>;
- template<typename _Range>
+ template<ranges::contiguous_range _Range>
span(_Range &&)
-> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
template<typename _Type, size_t _Extent>
+ [[nodiscard]]
inline
span<const byte, _Extent == dynamic_extent
? dynamic_extent : _Extent * sizeof(_Type)>
}
template<typename _Type, size_t _Extent>
+ requires (!is_const_v<_Type>)
inline
span<byte, _Extent == dynamic_extent
? dynamic_extent : _Extent * sizeof(_Type)>
- as_writable_bytes(span<_Type, _Extent> __sp) noexcept
+ as_writable_bytes [[nodiscard]] (span<_Type, _Extent> __sp) noexcept
{
auto data = reinterpret_cast<byte*>(__sp.data());
auto size = __sp.size_bytes();
// Opt-in to view concept
template<typename _ElementType, size_t _Extent>
inline constexpr bool
- enable_view<span<_ElementType, _Extent>>
- = _Extent == 0 || _Extent == dynamic_extent;
+ enable_view<span<_ElementType, _Extent>> = true;
}
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#endif // concepts
-#endif // C++20
+#endif // __cpp_lib_span
#endif // _GLIBCXX_SPAN