//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 // // template // constexpr explicit(see below) // mapping(const StridedLayoutMapping& other) noexcept; // // Constraints: // - layout-mapping-alike is satisfied. // - is_constructible_v is true. // - StridedLayoutMapping::is_always_unique() is true. // - StridedLayoutMapping::is_always_strided() is true. // // Preconditions: // - StridedLayoutMapping meets the layout mapping requirements ([mdspan.layout.policy.reqmts]), // - other.stride(r) > 0 is true for every rank index r of extents(), // - other.required_span_size() is representable as a value of type index_type ([basic.fundamental]), and // - OFFSET(other) == 0 is true. // // Effects: Direct-non-list-initializes extents_ with other.extents(), and for all d in the range [0, rank_), // direct-non-list-initializes strides_[d] with other.stride(d). // // Remarks: The expression inside explicit is equivalent to: // - !(is_convertible_v && // (is-mapping-of || // is-mapping-of || // is-mapping-of)) #include #include #include #include // dynamic_extent #include #include "test_macros.h" #include "../CustomTestLayouts.h" template constexpr void test_conversion(FromE src_exts) { using To = std::layout_stride::mapping; using From = typename FromL::template mapping; From src([&]() { if constexpr (std::is_same_v) { // just construct some strides which aren't layout_left/layout_right std::array strides; size_t stride = 2; for (size_t r = 0; r < FromE::rank(); r++) { strides[r] = stride; stride *= src_exts.extent(r); } return From(src_exts, strides); } else { return From(src_exts); } }()); ASSERT_NOEXCEPT(To(src)); To dest(src); assert(dest == src); if constexpr (implicit) { To dest_implicit = src; assert(dest_implicit == src); } else { assert((!std::is_convertible_v)); } } template constexpr void test_conversion() { constexpr size_t D = std::dynamic_extent; constexpr bool idx_convertible = static_cast(std::numeric_limits::max()) >= static_cast(std::numeric_limits::max()); constexpr bool l_convertible = std::is_same_v || std::is_same_v || std::is_same_v; constexpr bool idx_l_convertible = idx_convertible && l_convertible; // clang-format off // adding extents convertibility expectation test_conversion>(std::extents()); test_conversion>(std::extents(0)); test_conversion>(std::extents(5)); test_conversion>(std::extents(5)); test_conversion>(std::extents()); test_conversion>(std::extents(5, 5)); test_conversion>(std::extents(5, 5)); test_conversion>(std::extents(5)); test_conversion>(std::extents()); test_conversion>(std::extents(5, 7)); test_conversion>( std::extents(5, 7, 8, 9, 1)); test_conversion>(std::extents(5)); test_conversion>(std::extents()); // clang-format on } template using ToM = std::layout_stride::mapping>; template using FromM = typename FromL::template mapping>; template constexpr void test_no_implicit_conversion() { constexpr size_t D = std::dynamic_extent; // Sanity check that one static to dynamic conversion works static_assert(std::is_constructible_v, FromM>); static_assert(std::is_convertible_v, ToM>); // Check that dynamic to static conversion only works explicitly static_assert(std::is_constructible_v, FromM>); static_assert(!std::is_convertible_v, ToM>); // Sanity check that one static to dynamic conversion works static_assert(std::is_constructible_v, FromM>); static_assert(std::is_convertible_v, ToM>); // Check that dynamic to static conversion only works explicitly static_assert(std::is_constructible_v, FromM>); static_assert(!std::is_convertible_v, ToM>); // Sanity check that smaller index_type to larger index_type conversion works static_assert(std::is_constructible_v, FromM>); static_assert(std::is_convertible_v, ToM>); // Check that larger index_type to smaller index_type conversion works explicitly only static_assert(std::is_constructible_v, FromM>); static_assert(!std::is_convertible_v, ToM>); } template constexpr void test_rank_mismatch() { constexpr size_t D = std::dynamic_extent; static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); } template constexpr void test_static_extent_mismatch() { constexpr size_t D = std::dynamic_extent; static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); static_assert(!std::is_constructible_v, FromM>); } template constexpr void test_layout() { test_conversion(); test_conversion(); test_conversion(); test_conversion(); // the implicit convertibility test doesn't apply to non std::layouts if constexpr (!std::is_same_v) test_no_implicit_conversion(); test_rank_mismatch(); test_static_extent_mismatch(); } constexpr bool test() { test_layout(); test_layout(); test_layout(); test_layout(); return true; } int main(int, char**) { test(); static_assert(test()); return 0; }