diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 669ba378eca..5bc6c74f0f1 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -11,11 +11,8 @@ #if !_HAS_CXX23 || !defined(__cpp_lib_concepts) // TRANSITION, GH-395 _EMIT_STL_WARNING(STL4038, "The contents of are available only with C++23 or later."); #else // ^^^ not supported / supported language mode vvv -#include #include #include -#include -#include #pragma pack(push, _CRT_PACKING) #pragma warning(push, _STL_WARNING_LEVEL) @@ -251,20 +248,6 @@ inline constexpr bool _Is_extents = false; template inline constexpr bool _Is_extents> = true; -template -struct _Layout_mapping_alike_helper : false_type {}; - -template -struct _Layout_mapping_alike_helper<_Mapping, - void_t, - is_same, - is_same, bool_constant<_Mapping::is_always_strided()>, - bool_constant<_Mapping::is_always_exhaustive()>, bool_constant<_Mapping::is_always_unique()>>> - : bool_constant<_Is_extents> {}; - -template -struct _Layout_mapping_alike : bool_constant<_Layout_mapping_alike_helper<_Mapping>::value> {}; - template inline constexpr bool _Is_mapping_of = is_same_v, _Mapping>; @@ -307,18 +290,20 @@ public: constexpr mapping(const _Extents& _Ext) noexcept : _Myext(_Ext) {} - template , int> = 0> + template + requires is_constructible_v<_Extents, _OtherExtents> constexpr explicit(!is_convertible_v<_OtherExtents, _Extents>) mapping(const mapping<_OtherExtents>& _Other) noexcept : _Myext{_Other.extents()} {} - template , int> = 0> + template + requires (_Extents::rank() <= 1) && is_constructible_v<_Extents, _OtherExtents> constexpr explicit(!is_convertible_v<_OtherExtents, _Extents>) mapping(const layout_right::mapping<_OtherExtents>& _Other) noexcept : _Myext{_Other.extents()} {} - template , int> = 0> + template + requires is_constructible_v<_Extents, _OtherExtents> constexpr explicit(_Extents::rank() > 0) mapping(const layout_stride::template mapping<_OtherExtents>& _Other) : _Myext{_Other.extents()} {} @@ -337,10 +322,9 @@ public: return _Result; } - template && ...) - && (is_nothrow_constructible_v && ...), - int> = 0> + template + requires (sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) + && (is_nothrow_constructible_v && ...) _NODISCARD constexpr index_type operator()(_Indices... _Idx) const noexcept { return _Index_impl...>( static_cast(_Idx)..., make_index_sequence<_Extents::rank()>{}); @@ -370,8 +354,9 @@ public: return true; } - template 0), int> = 0> - _NODISCARD constexpr index_type stride(const rank_type _Rank) const noexcept { + _NODISCARD constexpr index_type stride(const rank_type _Rank) const noexcept + requires (extents_type::rank() > 0) + { index_type _Result = 1; for (rank_type _Dim = 0; _Dim < _Rank; ++_Dim) { _Result *= _Myext.extent(_Dim); @@ -381,6 +366,7 @@ public: } template + requires (extents_type::rank() == _OtherExtents::rank()) _NODISCARD_FRIEND constexpr bool operator==(const mapping& _Left, const mapping<_OtherExtents>& _Right) noexcept { return _Left.extents() == _Right.extents(); } @@ -418,18 +404,20 @@ public: constexpr mapping(const _Extents& _Ext) noexcept : _Myext(_Ext) {} - template , int> = 0> + template + requires is_constructible_v constexpr explicit(!is_convertible_v<_OtherExtents, _Extents>) mapping(const mapping<_OtherExtents>& _Other) noexcept : _Myext{_Other.extents()} {} - template , int> = 0> + template + requires (extents_type::rank() <= 1) && is_constructible_v constexpr explicit(!is_convertible_v<_OtherExtents, _Extents>) mapping(const layout_left::mapping<_OtherExtents>& _Other) noexcept : _Myext{_Other.extents()} {} - template , int> = 0> + template + requires is_constructible_v constexpr explicit(_Extents::rank() > 0) mapping(const layout_stride::template mapping<_OtherExtents>& _Other) : _Myext{_Other.extents()} {} @@ -448,10 +436,9 @@ public: return _Result; } - template && ...) - && (is_nothrow_constructible_v && ...), - int> = 0> + template + requires (sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) + && (is_nothrow_constructible_v && ...) _NODISCARD constexpr index_type operator()(_Indices... _Idx) const noexcept { return _Index_impl...>( static_cast(_Idx)..., make_index_sequence<_Extents::rank()>{}); @@ -481,8 +468,9 @@ public: return true; } - template 0), int> = 0> - _NODISCARD constexpr index_type stride(const rank_type _Rank) const noexcept { + _NODISCARD constexpr index_type stride(const rank_type _Rank) const noexcept + requires (extents_type::rank() > 0) + { index_type _Result = 1; for (rank_type _Dim = _Rank + 1; _Dim < _Extents::rank(); ++_Dim) { _Result *= _Myext.extent(_Dim); @@ -492,6 +480,7 @@ public: } template + requires (extents_type::rank() == _OtherExtents::rank()) _NODISCARD_FRIEND constexpr bool operator==(const mapping& _Left, const mapping<_OtherExtents>& _Right) noexcept { return _Left.extents() == _Right.extents(); } @@ -507,6 +496,17 @@ private: } }; +template +concept _Layout_mapping_alike = requires { + requires _Is_extents; + { _Mp::is_always_strided() } -> same_as; + { _Mp::is_always_exhaustive() } -> same_as; + { _Mp::is_always_unique() } -> same_as; + bool_constant<_Mp::is_always_strided()>::value; + bool_constant<_Mp::is_always_exhaustive()>::value; + bool_constant<_Mp::is_always_unique()>::value; + }; + template class layout_stride::mapping { public: @@ -525,38 +525,45 @@ public: constexpr mapping() noexcept = default; constexpr mapping(const mapping&) noexcept = default; - template , int> = 0> - constexpr mapping(const _Extents& _E_, const array<_OtherIndexType, _Extents::rank()>& _S_) noexcept : _Myext{_E_} { +#ifndef __clang__ // TRANSITION, MSVC messes up CTAD when concepts are used here (needs further investigation) + template + && is_nothrow_constructible_v, + int> = 0> +#else // ^^^ workaround / no workaround vvv + template + requires is_convertible_v + && is_nothrow_constructible_v +#endif // ^^^ no workaround ^^^ + constexpr mapping(const _Extents& _E_, const span<_OtherIndexType, _Extents::rank()> _S_) noexcept : _Myext{_E_} { for (rank_type _Idx = 0; _Idx < _Extents::rank(); ++_Idx) { _Mystrides[_Idx] = _S_[_Idx]; } }; - template , int> = 0> - constexpr mapping(const _Extents& _E_, const span<_OtherIndexType, _Extents::rank()> _S_) noexcept : _Myext{_E_} { +#ifndef __clang__ // TRANSITION, MSVC messes up CTAD when concepts are used here (needs further investigation) + template + && is_nothrow_constructible_v, + int> = 0> +#else // ^^^ workaround / no workaround vvv + template + requires is_convertible_v + && is_nothrow_constructible_v +#endif // ^^^ no workaround ^^^ + constexpr mapping(const extents_type& _E_, const array<_OtherIndexType, extents_type::rank()>& _S_) noexcept + : _Myext{_E_} { for (rank_type _Idx = 0; _Idx < _Extents::rank(); ++_Idx) { _Mystrides[_Idx] = _S_[_Idx]; } }; - template , int> = 0> - constexpr explicit(!is_convertible_v<_OtherExtents, _Extents>) - mapping(const mapping<_OtherExtents>& _Other) noexcept - : _Myext{_Other.extents()}, _Mystrides{_Other.strides()} { - for (rank_type _Idx = 0; _Idx < _Extents::rank(); ++_Idx) { - _Mystrides[_Idx] = _Other.stride(_Idx); - } - } - - template ::value - && is_constructible_v - && _StridedLayoutMapping::is_always_unique() && _StridedLayoutMapping::is_always_strided(), - int> = 0> - constexpr explicit( - !is_convertible_v + template + requires _Layout_mapping_alike<_StridedLayoutMapping> + && is_constructible_v + && (_StridedLayoutMapping::is_always_unique()) && (_StridedLayoutMapping::is_always_strided()) + constexpr explicit(!( + is_convertible_v && (_Is_mapping_of || _Is_mapping_of - || _Is_mapping_of) ) + || _Is_mapping_of) )) mapping(const _StridedLayoutMapping& _Other) noexcept : _Myext(_Other.extents()) { for (rank_type _Dim = 0; _Dim < _Extents::rank(); ++_Dim) { @@ -592,10 +599,9 @@ public: } } - template && ...) - && (is_nothrow_constructible_v && ...), - int> = 0> + template + requires (sizeof...(_Indices) == extents_type::rank()) && (is_convertible_v<_Indices, index_type> && ...) + && (is_nothrow_constructible_v && ...) _NODISCARD constexpr index_type operator()(_Indices... _Idx) const noexcept { return _Index_impl...>( static_cast(_Idx)..., make_index_sequence<_Extents::rank()>{}); @@ -630,15 +636,13 @@ public: return true; } - template 0), int> = 0> _NODISCARD constexpr index_type stride(const rank_type _Idx) const noexcept { return _Mystrides[_Idx]; } - template ::value - && extents_type::rank() == _OtherMapping::extents_type::rank() - && _OtherMapping::is_always_strided(), - int> = 0> + template + requires _Layout_mapping_alike<_OtherMapping> && (extents_type::rank() == _OtherMapping::extents_type::rank()) + && (_OtherMapping::is_always_strided()) _NODISCARD_FRIEND constexpr bool operator==(const mapping& _Left, const _OtherMapping& _Right) noexcept { if (_Left.extents() != _Right.extents()) { return false; @@ -696,10 +700,8 @@ struct default_accessor { constexpr default_accessor() noexcept = default; - template ::element_type (*)[], _ElementType (*)[]>, - int> = 0> + template + requires is_convertible_v<_OtherElementType (*)[], element_type (*)[]> constexpr default_accessor(default_accessor<_OtherElementType>) noexcept {} _NODISCARD constexpr data_handle_type offset(data_handle_type _Ptr, size_t _Idx) const noexcept { @@ -752,64 +754,54 @@ public: return _Extents::static_extent(_Rank); } - template 0) && is_default_constructible_v - && is_default_constructible_v<_Mapping> && is_default_constructible_v, - int> = 0> - constexpr mdspan() {} + constexpr mdspan() + requires (rank_dynamic() > 0) && is_default_constructible_v + && is_default_constructible_v && is_default_constructible_v + {} constexpr mdspan(const mdspan&) = default; constexpr mdspan(mdspan&&) = default; - template && is_default_constructible_v, - int> = 0> - constexpr explicit mdspan(data_handle_type _Ptr_) : _Ptr{_STD move(_Ptr_)}, _Map{extents_type{}} {} - - template 0)) && (is_convertible_v<_OtherIndexTypes, index_type> && ...) - && (is_nothrow_constructible_v && ...) - //&& (sizeof...(_OtherIndexTypes) == rank() || sizeof...(_OtherIndexTypes) == rank_dynamic()) - && is_constructible_v && is_default_constructible_v, - int> = 0> + template + requires (is_convertible_v<_OtherIndexTypes, index_type> && ...) + && (is_nothrow_constructible_v && ...) + && (sizeof...(_OtherIndexTypes) > 0) + && (sizeof...(_OtherIndexTypes) == rank() || sizeof...(_OtherIndexTypes) == rank_dynamic()) + && is_constructible_v && is_default_constructible_v constexpr explicit mdspan(data_handle_type _Ptr_, _OtherIndexTypes... _Exts) : _Ptr{_STD move(_Ptr_)}, _Map{extents_type{static_cast(_STD move(_Exts))...}} {} - template - && is_nothrow_constructible_v - && (_Size == rank() || _Size == rank_dynamic()) - && is_constructible_v && is_default_constructible_v, - int> = 0> + template + requires is_convertible_v<_OtherIndexType, index_type> + && is_nothrow_constructible_v + && (_Size == rank() || _Size == rank_dynamic()) + && is_constructible_v && is_default_constructible_v constexpr explicit(_Size != rank_dynamic()) mdspan(data_handle_type _Ptr_, span<_OtherIndexType, _Size>& _Exts) : _Ptr{_Ptr_}, _Map{_Extents{_Exts}} {} - template - && is_nothrow_constructible_v - && (_Size == rank() || _Size == rank_dynamic()) - && is_constructible_v && is_default_constructible_v, - int> = 0> + template + requires is_convertible_v + && is_nothrow_constructible_v + && (_Size == rank() || _Size == rank_dynamic()) + && is_constructible_v && is_default_constructible_v constexpr explicit(_Size != rank_dynamic()) mdspan(data_handle_type _Ptr_, const array<_OtherIndexType, _Size>& _Exts) : _Ptr{_Ptr_}, _Map{_Extents{_Exts}} {} - template && is_default_constructible_v, int> = 0> - constexpr mdspan(data_handle_type _Ptr_, const _Extents& _Ext) : _Ptr{_Ptr_}, _Map{_Ext} {} + constexpr mdspan(data_handle_type _Ptr_, const extents_type& _Ext) + requires is_constructible_v && is_default_constructible_v + : _Ptr{_Ptr_}, _Map{_Ext} {} - template , int> = 0> - constexpr mdspan(data_handle_type _Ptr_, const mapping_type& _Map_) : _Ptr{_Ptr_}, _Map{_Map_} {} + constexpr mdspan(data_handle_type _Ptr_, const mapping_type& _Map_) + requires is_default_constructible_v + : _Ptr{_Ptr_}, _Map{_Map_} {} constexpr mdspan(data_handle_type _Ptr_, const mapping_type& _Map_, const accessor_type& _Acc_) : _Ptr{_Ptr_}, _Map{_Map_}, _Acc{_Acc_} {} - template &> - && is_constructible_v, - int> = 0> + template + requires is_constructible_v&> + && is_constructible_v constexpr explicit( !is_convertible_v&, mapping_type> || !is_convertible_v) @@ -825,22 +817,25 @@ public: constexpr mdspan& operator=(const mdspan&) = default; constexpr mdspan& operator=(mdspan&&) = default; - // TRANSITION operator[](const _OtherIndexTypes... _Indices) - template && ...) - && (is_nothrow_constructible_v && ...), - /*&& sizeof...(_OtherIndexTypes) == rank(),*/ - int> = 0> + // TRANSITION, P2128R6 (Multidimensional subscript operator) + template + requires (is_convertible_v<_OtherIndexTypes, index_type> && ...) + && (is_nothrow_constructible_v && ...) + && (sizeof...(_OtherIndexTypes) == rank()) _NODISCARD constexpr reference operator()(const _OtherIndexTypes... _Indices) const { return _Acc.access(_Ptr, _Map(static_cast(_STD move(_Indices))...)); } - template , int> = 0> + template + requires is_convertible_v + && is_nothrow_constructible_v _NODISCARD constexpr reference operator[](span<_OtherIndexType, rank()> _Indices) const { return _Index_impl(_Indices, make_index_sequence{}); } - template , int> = 0> + template + requires is_convertible_v + && is_nothrow_constructible_v _NODISCARD constexpr reference operator[](const array<_OtherIndexType, rank()>& _Indices) const { return _Index_impl(_Indices, make_index_sequence{}); } @@ -930,12 +925,43 @@ private: accessor_type _Acc{}; }; +template + requires (is_array_v<_CArray> && rank_v<_CArray> == 1) +mdspan(_CArray&) -> mdspan, extents>>; + +template + requires (is_pointer_v>) +mdspan(_Pointer&&) -> mdspan>, extents>; + +template + requires ((is_convertible_v<_Integrals, size_t> && ...) && sizeof...(_Integrals) > 0) +explicit mdspan(_ElementType*, _Integrals...) -> mdspan<_ElementType, dextents>; + +template +mdspan(_ElementType*, span<_OtherIndexType, _Nx>) -> mdspan<_ElementType, dextents>; + +template +mdspan(_ElementType*, const array<_OtherIndexType, _Nx>&) -> mdspan<_ElementType, dextents>; + +template +mdspan(_ElementType*, const extents<_IndexType, _ExtentsPack...>&) + -> mdspan<_ElementType, extents<_IndexType, _ExtentsPack...>>; + +template +mdspan(_ElementType*, const _MappingType&) + -> mdspan<_ElementType, typename _MappingType::extents_type, typename _MappingType::layout_type>; + +template +mdspan(const typename _AccessorType::data_handle_type&, const _MappingType&, const _AccessorType&) + -> mdspan; + _STD_END #pragma pop_macro("new") _STL_RESTORE_CLANG_WARNINGS #pragma warning(pop) #pragma pack(pop) -#endif // _HAS_CXX23 +#endif // ^^^ supported language mode ^^^ #endif // _STL_COMPILER_PREPROCESSOR #endif // _MDSPAN_ diff --git a/tests/std/tests/P0009R18_mdspan/test.cpp b/tests/std/tests/P0009R18_mdspan/test.cpp index b653696e29c..6e0ad595689 100644 --- a/tests/std/tests/P0009R18_mdspan/test.cpp +++ b/tests/std/tests/P0009R18_mdspan/test.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include #include