Skip to content

Commit ab863b3

Browse files
crtrotttru
authored andcommitted
[libc++][mdspan] Implement std::mdspan class
This implements P0009 std::mdspan ((https://wg21.link/p0009)), a multidimensional span with customization points for layouts and data access. Co-authored-by: Damien L-G <dalg24@gmail.com> Differential Revision: https://reviews.llvm.org/154367
1 parent 397390a commit ab863b3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+4141
-26
lines changed

libcxx/docs/ReleaseNotes/17.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Implemented Papers
6969
- P2585R0 - Improving default container formatting
7070
- P0408R7 - Efficient Access to ``basic_stringbuf``'s Buffer
7171
- P2474R2 - ``views::repeat``
72+
- P0009R18 - ``mdspan`` (``layout_stride`` is not done yet)
7273

7374
Improvements and New Features
7475
-----------------------------

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,7 @@ set(files
484484
__mdspan/extents.h
485485
__mdspan/layout_left.h
486486
__mdspan/layout_right.h
487+
__mdspan/mdspan.h
487488
__memory/addressof.h
488489
__memory/align.h
489490
__memory/aligned_alloc.h

libcxx/include/__mdspan/extents.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,8 @@ class extents {
315315
}
316316

317317
template <class _OtherIndexType, size_t _Size>
318-
requires(is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType> &&
318+
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
319+
is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&
319320
(_Size == __rank_ || _Size == __rank_dynamic_))
320321
explicit(_Size != __rank_dynamic_)
321322
_LIBCPP_HIDE_FROM_ABI constexpr extents(const array<_OtherIndexType, _Size>& __exts) noexcept
@@ -325,7 +326,8 @@ class extents {
325326
}
326327

327328
template <class _OtherIndexType, size_t _Size>
328-
requires(is_convertible_v<_OtherIndexType, index_type> && is_nothrow_constructible_v<index_type, _OtherIndexType> &&
329+
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
330+
is_nothrow_constructible_v<index_type, const _OtherIndexType&> &&
329331
(_Size == __rank_ || _Size == __rank_dynamic_))
330332
explicit(_Size != __rank_dynamic_)
331333
_LIBCPP_HIDE_FROM_ABI constexpr extents(const span<_OtherIndexType, _Size>& __exts) noexcept

libcxx/include/__mdspan/layout_left.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,17 @@ class layout_left::mapping {
7575
_LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default;
7676
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default;
7777
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) {
78-
_LIBCPP_ASSERT(__required_span_size_is_representable(__ext),
79-
"layout_left::mapping extents ctor: product of extents must be representable as index_type.");
78+
_LIBCPP_ASSERT_UNCATEGORIZED(
79+
__required_span_size_is_representable(__ext),
80+
"layout_left::mapping extents ctor: product of extents must be representable as index_type.");
8081
}
8182

8283
template <class _OtherExtents>
8384
requires(is_constructible_v<extents_type, _OtherExtents>)
8485
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
8586
mapping(const mapping<_OtherExtents>& __other) noexcept
8687
: __extents_(__other.extents()) {
87-
_LIBCPP_ASSERT(
88+
_LIBCPP_ASSERT_UNCATEGORIZED(
8889
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
8990
"layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type.");
9091
}
@@ -94,7 +95,7 @@ class layout_left::mapping {
9495
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
9596
mapping(const layout_right::mapping<_OtherExtents>& __other) noexcept
9697
: __extents_(__other.extents()) {
97-
_LIBCPP_ASSERT(
98+
_LIBCPP_ASSERT_UNCATEGORIZED(
9899
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
99100
"layout_left::mapping converting ctor: other.required_span_size() must be representable as index_type.");
100101
}
@@ -122,8 +123,8 @@ class layout_left::mapping {
122123
requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) &&
123124
(is_nothrow_constructible_v<index_type, _Indices> && ...))
124125
_LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept {
125-
_LIBCPP_ASSERT(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
126-
"layout_left::mapping: out of bounds indexing");
126+
_LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
127+
"layout_left::mapping: out of bounds indexing");
127128
array<index_type, extents_type::rank()> __idx_a{static_cast<index_type>(__idx)...};
128129
return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
129130
index_type __res = 0;
@@ -144,7 +145,7 @@ class layout_left::mapping {
144145
_LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept
145146
requires(extents_type::rank() > 0)
146147
{
147-
_LIBCPP_ASSERT(__r < extents_type::rank(), "layout_left::mapping::stride(): invalid rank index");
148+
_LIBCPP_ASSERT_UNCATEGORIZED(__r < extents_type::rank(), "layout_left::mapping::stride(): invalid rank index");
148149
index_type __s = 1;
149150
for (rank_type __i = extents_type::rank() - 1; __i > __r; __i--)
150151
__s *= __extents_.extent(__i);
@@ -159,7 +160,7 @@ class layout_left::mapping {
159160
}
160161

161162
private:
162-
extents_type __extents_{}; // exposition only
163+
_LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
163164
};
164165

165166
#endif // _LIBCPP_STD_VER >= 23

libcxx/include/__mdspan/layout_right.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,17 @@ class layout_right::mapping {
7474
_LIBCPP_HIDE_FROM_ABI constexpr mapping() noexcept = default;
7575
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const mapping&) noexcept = default;
7676
_LIBCPP_HIDE_FROM_ABI constexpr mapping(const extents_type& __ext) noexcept : __extents_(__ext) {
77-
_LIBCPP_ASSERT(__required_span_size_is_representable(__ext),
78-
"layout_right::mapping extents ctor: product of extents must be representable as index_type.");
77+
_LIBCPP_ASSERT_UNCATEGORIZED(
78+
__required_span_size_is_representable(__ext),
79+
"layout_right::mapping extents ctor: product of extents must be representable as index_type.");
7980
}
8081

8182
template <class _OtherExtents>
8283
requires(is_constructible_v<extents_type, _OtherExtents>)
8384
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
8485
mapping(const mapping<_OtherExtents>& __other) noexcept
8586
: __extents_(__other.extents()) {
86-
_LIBCPP_ASSERT(
87+
_LIBCPP_ASSERT_UNCATEGORIZED(
8788
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
8889
"layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
8990
}
@@ -93,7 +94,7 @@ class layout_right::mapping {
9394
_LIBCPP_HIDE_FROM_ABI constexpr explicit(!is_convertible_v<_OtherExtents, extents_type>)
9495
mapping(const layout_left::mapping<_OtherExtents>& __other) noexcept
9596
: __extents_(__other.extents()) {
96-
_LIBCPP_ASSERT(
97+
_LIBCPP_ASSERT_UNCATEGORIZED(
9798
__mdspan_detail::__is_representable_as<index_type>(__other.required_span_size()),
9899
"layout_right::mapping converting ctor: other.required_span_size() must be representable as index_type.");
99100
}
@@ -121,8 +122,8 @@ class layout_right::mapping {
121122
requires((sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) &&
122123
(is_nothrow_constructible_v<index_type, _Indices> && ...))
123124
_LIBCPP_HIDE_FROM_ABI constexpr index_type operator()(_Indices... __idx) const noexcept {
124-
_LIBCPP_ASSERT(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
125-
"layout_right::mapping: out of bounds indexing");
125+
_LIBCPP_ASSERT_UNCATEGORIZED(__mdspan_detail::__is_multidimensional_index_in(__extents_, __idx...),
126+
"layout_right::mapping: out of bounds indexing");
126127
return [&]<size_t... _Pos>(index_sequence<_Pos...>) {
127128
index_type __res = 0;
128129
((__res = static_cast<index_type>(__idx) + __extents_.extent(_Pos) * __res), ...);
@@ -141,7 +142,7 @@ class layout_right::mapping {
141142
_LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const noexcept
142143
requires(extents_type::rank() > 0)
143144
{
144-
_LIBCPP_ASSERT(__r < extents_type::rank(), "layout_right::mapping::stride(): invalid rank index");
145+
_LIBCPP_ASSERT_UNCATEGORIZED(__r < extents_type::rank(), "layout_right::mapping::stride(): invalid rank index");
145146
index_type __s = 1;
146147
for (rank_type __i = extents_type::rank() - 1; __i > __r; __i--)
147148
__s *= __extents_.extent(__i);
@@ -156,7 +157,7 @@ class layout_right::mapping {
156157
}
157158

158159
private:
159-
extents_type __extents_{}; // exposition only
160+
_LIBCPP_NO_UNIQUE_ADDRESS extents_type __extents_{};
160161
};
161162

162163
#endif // _LIBCPP_STD_VER >= 23

0 commit comments

Comments
 (0)