diff --git a/stl/inc/mdspan b/stl/inc/mdspan index 8f86197b54a..1662777b8d8 100644 --- a/stl/inc/mdspan +++ b/stl/inc/mdspan @@ -752,6 +752,13 @@ struct default_accessor { using reference = _ElementType&; using data_handle_type = _ElementType*; + static_assert( + sizeof(element_type) > 0, "ElementType must be a complete type (N4944 [mdspan.accessor.default.overview]/2)."); + static_assert(!is_abstract_v, + "ElementType cannot be an abstract type (N4944 [mdspan.accessor.default.overview]/2)."); + static_assert( + !is_array_v, "ElementType cannot be an array type (N4944 [mdspan.accessor.default.overview]/2)."); + constexpr default_accessor() noexcept = default; template diff --git a/tests/std/include/test_mdspan_support.hpp b/tests/std/include/test_mdspan_support.hpp index 16d66474179..842065b9051 100644 --- a/tests/std/include/test_mdspan_support.hpp +++ b/tests/std/include/test_mdspan_support.hpp @@ -11,7 +11,7 @@ enum class IsNothrow : bool { no, yes }; -template +template struct ConvertibleToInt { constexpr operator Int() const noexcept(std::to_underlying(Nothrow)) { return Int{1}; @@ -20,53 +20,57 @@ struct ConvertibleToInt { struct NonConvertibleToAnything {}; -template -constexpr void check_implicit_conversion(T); // not defined +namespace detail { + template + constexpr void check_implicit_conversion(T); // not defined +} // clang-format off template concept NotImplicitlyConstructibleFrom = std::constructible_from - && !requires(Args&&... args) { check_implicit_conversion({std::forward(args)...}); }; + && !requires(Args&&... args) { detail::check_implicit_conversion({std::forward(args)...}); }; // clang-format on -template -inline constexpr bool is_extents_v = false; - -template -inline constexpr bool is_extents_v> = true; - -template -inline constexpr bool is_mapping_of_v = - std::is_same_v, Mapping>; - -template -concept CheckNestedTypesOfLayoutMapping = - requires { - requires is_extents_v; - requires std::same_as; - requires std::same_as; - requires is_mapping_of_v; - }; - -template -concept CheckMemberFunctionsOfLayoutMapping = requires(const M m) { - { m.extents() } -> std::same_as; - { m.required_span_size() } -> std::same_as; - { m.is_unique() } -> std::same_as; - { m.is_exhaustive() } -> std::same_as; - { m.is_strided() } -> std::same_as; - }; - -template -concept CheckStaticFunctionsOfLayoutMapping = requires(const M m) { - { M::is_always_strided() } -> std::same_as; - { M::is_always_exhaustive() } -> std::same_as; - { M::is_always_unique() } -> std::same_as; - std::bool_constant::value; - std::bool_constant::value; - std::bool_constant::value; - }; +namespace detail { + template + inline constexpr bool is_extents_v = false; + + template + inline constexpr bool is_extents_v> = true; + + template + inline constexpr bool is_mapping_of_v = + std::is_same_v, Mapping>; + + template + concept CheckNestedTypesOfLayoutMapping = is_extents_v + && std::same_as + && std::same_as + && is_mapping_of_v; + + // clang-format off + template + concept CheckMemberFunctionsOfLayoutMapping = + requires(const M m) { + { m.extents() } -> std::same_as; + { m.required_span_size() } -> std::same_as; + { m.is_unique() } -> std::same_as; + { m.is_exhaustive() } -> std::same_as; + { m.is_strided() } -> std::same_as; + }; + // clang-format on + + template + concept CheckStaticFunctionsOfLayoutMapping = requires { + { M::is_always_strided() } -> std::same_as; + { M::is_always_exhaustive() } -> std::same_as; + { M::is_always_unique() } -> std::same_as; + std::bool_constant::value; + std::bool_constant::value; + std::bool_constant::value; + }; +} // namespace detail // clang-format off template @@ -89,9 +93,9 @@ constexpr bool check_layout_mapping_requirements() { static_assert(std::is_nothrow_move_constructible_v); static_assert(std::is_nothrow_move_assignable_v); static_assert(std::is_nothrow_swappable_v); - static_assert(CheckNestedTypesOfLayoutMapping); - static_assert(CheckMemberFunctionsOfLayoutMapping); - static_assert(CheckStaticFunctionsOfLayoutMapping); + static_assert(detail::CheckNestedTypesOfLayoutMapping); + static_assert(detail::CheckMemberFunctionsOfLayoutMapping); + static_assert(detail::CheckStaticFunctionsOfLayoutMapping); [](std::index_sequence) { static_assert(CheckCallOperatorOfLayoutMapping); @@ -106,7 +110,7 @@ constexpr bool check_layout_mapping_requirements() { } template - requires is_extents_v + requires detail::is_extents_v constexpr bool check_layout_mapping_policy_requirements() { using X = typename MP::template mapping; static_assert(check_layout_mapping_requirements()); @@ -114,3 +118,41 @@ constexpr bool check_layout_mapping_policy_requirements() { static_assert(std::same_as); return true; } + +template +constexpr bool check_accessor_policy_requirements(); + +namespace detail { + template + concept CheckNestedTypesOfAccessorPolicy = + sizeof(typename A::element_type) > 0 + && (!std::is_abstract_v) && std::copyable + && std::is_nothrow_move_constructible_v + && std::is_nothrow_move_assignable_v + && std::is_nothrow_swappable_v + && std::common_reference_with + && (std::same_as + || check_accessor_policy_requirements()) + && std::constructible_from + && std::is_same_v; + + // clang-format off + template + concept CheckMemberFunctionsOfAccessorPolicy = + requires(const A a, const typename A::data_handle_type p, size_t i) { + { a.access(p, i) } -> std::same_as; + { a.offset(p, i) } -> std::same_as; + }; + // clang-format on +} // namespace detail + +template +constexpr bool check_accessor_policy_requirements() { + static_assert(std::copyable); + static_assert(std::is_nothrow_move_constructible_v); + static_assert(std::is_nothrow_move_assignable_v); + static_assert(std::is_nothrow_swappable_v); + static_assert(detail::CheckNestedTypesOfAccessorPolicy); + static_assert(detail::CheckMemberFunctionsOfAccessorPolicy); + return true; +} diff --git a/tests/std/tests/P0009R18_mdspan_default_accessor/test.cpp b/tests/std/tests/P0009R18_mdspan_default_accessor/test.cpp index 21379295e76..9036a910c75 100644 --- a/tests/std/tests/P0009R18_mdspan_default_accessor/test.cpp +++ b/tests/std/tests/P0009R18_mdspan_default_accessor/test.cpp @@ -9,12 +9,17 @@ #include #include +#include + using namespace std; template constexpr void test_one(array elems) { using Accessor = default_accessor; + // default_accessor meets the accessor policy requirements + static_assert(check_accessor_policy_requirements()); + // Check modeled concepts static_assert(is_nothrow_move_constructible_v); static_assert(is_nothrow_move_assignable_v);