Skip to content

Commit

Permalink
Check preconditions of mdspan::operator[] clarified by LWG-3974
Browse files Browse the repository at this point in the history
  • Loading branch information
frederick-vs-ja committed Nov 22, 2023
1 parent 730af17 commit a82957c
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 0 deletions.
24 changes: 24 additions & 0 deletions stl/inc/mdspan
Original file line number Diff line number Diff line change
Expand Up @@ -1131,6 +1131,22 @@ struct _Mdspan_accessor_base<_AccessorPolicy> {
static constexpr _AccessorPolicy _Acc{};
};

#if _CONTAINER_DEBUG_LEVEL > 0
template <class _IndexType, class _OtherIndexType>
_NODISCARD constexpr _IndexType _Mdspan_checked_index_cast(_OtherIndexType&& _Idx) noexcept(
is_nothrow_constructible_v<_IndexType, _OtherIndexType>) {
_STL_INTERNAL_STATIC_ASSERT(is_integral_v<_IndexType> && is_constructible_v<_IndexType, _OtherIndexType>);

using _Arg_value_t = remove_cvref_t<_OtherIndexType>;
if constexpr (is_integral_v<_Arg_value_t> && !is_same_v<_Arg_value_t, bool>) {
_STL_VERIFY(_STD in_range<_IndexType>(_Idx),
"The index must be representable by index_type in order to be in a valid "
"multidimensional index (N4964 [mdspan.mdspan.members]/3).");
}
return static_cast<_IndexType>(_STD forward<_OtherIndexType>(_Idx));
}
#endif // _CONTAINER_DEBUG_LEVEL > 0

_EXPORT_STD template <class _ElementType, class _Extents, class _LayoutPolicy = layout_right,
class _AccessorPolicy = default_accessor<_ElementType>>
class __declspec(empty_bases) mdspan : private _Mdspan_mapping_base<_Extents, _LayoutPolicy>,
Expand Down Expand Up @@ -1278,7 +1294,11 @@ public:
&& (sizeof...(_OtherIndexTypes) == rank())
_NODISCARD constexpr reference operator[](_OtherIndexTypes... _Indices) const
noexcept(noexcept(_Access_impl(static_cast<index_type>(_STD move(_Indices))...))) /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
return _Access_impl(_STD _Mdspan_checked_index_cast<index_type>(_STD move(_Indices))...);
#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL <= 0 vvv
return _Access_impl(static_cast<index_type>(_STD move(_Indices))...);
#endif // ^^^ _CONTAINER_DEBUG_LEVEL <= 0 ^^^
}
#endif // ^^^ defined(__cpp_multidimensional_subscript) ^^^

Expand All @@ -1287,7 +1307,11 @@ private:
_NODISCARD constexpr reference _Multidimensional_subscript(
span<_OtherIndexType, rank()> _Indices, index_sequence<_Seq...>) const
noexcept(noexcept(_Access_impl(static_cast<index_type>(_STD as_const(_Indices[_Seq]))...))) {
#if _CONTAINER_DEBUG_LEVEL > 0
return _Access_impl(_STD _Mdspan_checked_index_cast<index_type>(_STD as_const(_Indices[_Seq]))...);
#else // ^^^ _CONTAINER_DEBUG_LEVEL > 0 / _CONTAINER_DEBUG_LEVEL <= 0 vvv
return _Access_impl(static_cast<index_type>(_STD as_const(_Indices[_Seq]))...);
#endif // ^^^ _CONTAINER_DEBUG_LEVEL <= 0 ^^^
}

public:
Expand Down
12 changes: 12 additions & 0 deletions tests/std/tests/P0009R18_mdspan_mdspan_death/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ void test_access_with_invalid_multidimensional_index_1() {
// I must be a multidimensional index in extents()
(void) mds[3, 4];
}

void test_access_with_nonrepresentable_index_1() {
mdspan mds{some_ints.data(), dextents<unsigned char, 2>{2, 3}};
(void) mds[256u, -255];
}
#endif // __cpp_multidimensional_subscript

void test_access_with_invalid_multidimensional_index_2() {
Expand All @@ -33,6 +38,11 @@ void test_access_with_invalid_multidimensional_index_2() {
(void) mds[array{4, 5}];
}

void test_access_with_nonrepresentable_index_2() {
mdspan mds{some_ints.data(), dextents<unsigned char, 2>{2, 3}};
(void) mds[array{256, -255}];
}

void test_size_when_index_type_is_signed() {
mdspan mds{some_ints.data(), dextents<signed char, 3>{8, 8, 4}};
// The size of the multidimensional index space extents() must be representable as a value of type size_type
Expand All @@ -51,8 +61,10 @@ int main(int argc, char* argv[]) {
test_construction_from_other_mdspan,
#ifdef __cpp_multidimensional_subscript // TRANSITION, P2128R6
test_access_with_invalid_multidimensional_index_1,
test_access_with_nonrepresentable_index_1,
#endif // __cpp_multidimensional_subscript
test_access_with_invalid_multidimensional_index_2,
test_access_with_nonrepresentable_index_2,
test_size_when_index_type_is_signed,
test_size_when_index_type_is_unsigned,
});
Expand Down

0 comments on commit a82957c

Please sign in to comment.