diff --git a/include/experimental/__p0009_bits/mdspan.hpp b/include/experimental/__p0009_bits/mdspan.hpp index 69f4fff6..0bac391c 100644 --- a/include/experimental/__p0009_bits/mdspan.hpp +++ b/include/experimental/__p0009_bits/mdspan.hpp @@ -24,6 +24,7 @@ #include #include +#include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { template < @@ -234,7 +235,7 @@ class mdspan { size_t r = 0; for (const auto& index : {indices...}) { - if (index >= __mapping_ref().extents().extent(r)) { + if (__is_index_oor(index, __mapping_ref().extents().extent(r))) { throw std::out_of_range( "mdspan::at(...," + std::to_string(index) + ",...) out-of-range at rank index " + std::to_string(r) + " for mdspan with extent {...," + std::to_string(__mapping_ref().extents().extent(r)) + ",...}"); @@ -254,7 +255,7 @@ class mdspan constexpr reference at(const std::array& indices) const { for (size_t r = 0; r < indices.size(); ++r) { - if (indices[r] >= __mapping_ref().extents().extent(r)) { + if (__is_index_oor(indices[r], __mapping_ref().extents().extent(r))) { throw std::out_of_range( "mdspan::at({...," + std::to_string(indices[r]) + ",...}) out-of-range at rank index " + std::to_string(r) + " for mdspan with extent {...," + std::to_string(__mapping_ref().extents().extent(r)) + ",...}"); @@ -274,7 +275,7 @@ class mdspan constexpr reference at(std::span indices) const { for (size_t r = 0; r < indices.size(); ++r) { - if (indices[r] >= __mapping_ref().extents().extent(r)) { + if (__is_index_oor(indices[r], __mapping_ref().extents().extent(r))) { throw std::out_of_range( "mdspan::at({...," + std::to_string(indices[r]) + ",...}) out-of-range at rank index " + std::to_string(r) + " for mdspan with extent {...," + std::to_string(__mapping_ref().extents().extent(r)) + ",...}"); @@ -441,6 +442,23 @@ class mdspan MDSPAN_FORCE_INLINE_FUNCTION constexpr mapping_type const& __mapping_ref() const noexcept { return __members.__second().__first(); } MDSPAN_FORCE_INLINE_FUNCTION _MDSPAN_CONSTEXPR_14 accessor_type& __accessor_ref() noexcept { return __members.__second().__second(); } MDSPAN_FORCE_INLINE_FUNCTION constexpr accessor_type const& __accessor_ref() const noexcept { return __members.__second().__second(); } + + MDSPAN_TEMPLATE_REQUIRES( + class SizeType, + /* requires */ ( + _MDSPAN_TRAIT(std::is_convertible, const SizeType&, index_type) && + _MDSPAN_TRAIT(std::is_nothrow_constructible, index_type, const SizeType&) + ) + ) + MDSPAN_FORCE_INLINE_FUNCTION constexpr bool __is_index_oor(SizeType index, index_type extent) const noexcept { + // Check for negative indices + if constexpr(std::is_signed_v) { + if(index < 0) { + return true; + } + } + return static_cast(index) >= extent; + } template friend class mdspan;