1cfa096d9SChristian Trott //===----------------------------------------------------------------------===// 2cfa096d9SChristian Trott // 3cfa096d9SChristian Trott // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4cfa096d9SChristian Trott // See https://llvm.org/LICENSE.txt for license information. 5cfa096d9SChristian Trott // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6cfa096d9SChristian Trott // 7cfa096d9SChristian Trott //===----------------------------------------------------------------------===// 8cfa096d9SChristian Trott 9cfa096d9SChristian Trott // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 10cfa096d9SChristian Trott 11cfa096d9SChristian Trott // <mdspan> 12cfa096d9SChristian Trott 13cfa096d9SChristian Trott // template<class OtherExtents> 14cfa096d9SChristian Trott // constexpr explicit(!is_convertible_v<OtherExtents, extents_type>) 15cfa096d9SChristian Trott // mapping(const mapping<OtherExtents>&) noexcept; 16cfa096d9SChristian Trott 17cfa096d9SChristian Trott // Constraints: is_constructible_v<extents_type, OtherExtents> is true. 18cfa096d9SChristian Trott // 19cfa096d9SChristian Trott // Preconditions: other.required_span_size() is representable as a value of type index_type 20cfa096d9SChristian Trott 21cfa096d9SChristian Trott #include <cassert> 22*e99c4906SNikolas Klauser #include <cstddef> 23cfa096d9SChristian Trott #include <limits> 24*e99c4906SNikolas Klauser #include <mdspan> 255e19fd17SLouis Dionne #include <span> // dynamic_extent 265e19fd17SLouis Dionne #include <type_traits> 27cfa096d9SChristian Trott 28cfa096d9SChristian Trott #include "test_macros.h" 29cfa096d9SChristian Trott 30cfa096d9SChristian Trott template <class To, class From> 31cfa096d9SChristian Trott constexpr void test_implicit_conversion(To dest, From src) { 32cfa096d9SChristian Trott assert(dest == src); 33cfa096d9SChristian Trott } 34cfa096d9SChristian Trott 35cfa096d9SChristian Trott template <bool implicit, class ToE, class FromE> 36cfa096d9SChristian Trott constexpr void test_conversion(FromE src_exts) { 37cfa096d9SChristian Trott using To = std::layout_right::mapping<ToE>; 38cfa096d9SChristian Trott using From = std::layout_right::mapping<FromE>; 39cfa096d9SChristian Trott From src(src_exts); 40cfa096d9SChristian Trott 41cfa096d9SChristian Trott ASSERT_NOEXCEPT(To(src)); 42cfa096d9SChristian Trott To dest(src); 43cfa096d9SChristian Trott 44cfa096d9SChristian Trott assert(dest == src); 45cfa096d9SChristian Trott if constexpr (implicit) { 46cfa096d9SChristian Trott dest = src; 47cfa096d9SChristian Trott assert(dest == src); 48cfa096d9SChristian Trott test_implicit_conversion<To, From>(src, src); 49cfa096d9SChristian Trott } 50cfa096d9SChristian Trott } 51cfa096d9SChristian Trott 52cfa096d9SChristian Trott template <class T1, class T2> 53cfa096d9SChristian Trott constexpr void test_conversion() { 54cfa096d9SChristian Trott constexpr size_t D = std::dynamic_extent; 55cfa096d9SChristian Trott constexpr bool idx_convertible = 56cfa096d9SChristian Trott static_cast<size_t>(std::numeric_limits<T1>::max()) >= static_cast<size_t>(std::numeric_limits<T2>::max()); 57cfa096d9SChristian Trott 58cfa096d9SChristian Trott // clang-format off 59cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1>>(std::extents<T2>()); 60cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, D>>(std::extents<T2, D>(5)); 61cfa096d9SChristian Trott test_conversion<idx_convertible && false, std::extents<T1, 5>>(std::extents<T2, D>(5)); 62cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, 5>>(std::extents<T2, 5>()); 63cfa096d9SChristian Trott test_conversion<idx_convertible && false, std::extents<T1, 5, D>>(std::extents<T2, D, D>(5, 5)); 64cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, D, D>>(std::extents<T2, D, D>(5, 5)); 65cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, D, D>>(std::extents<T2, D, 7>(5)); 66cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, 5, 7>>(std::extents<T2, 5, 7>()); 67cfa096d9SChristian Trott test_conversion<idx_convertible && false, std::extents<T1, 5, D, 8, D, D>>(std::extents<T2, D, D, 8, 9, 1>(5, 7)); 68cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, D, D, D, D, D>>( 69cfa096d9SChristian Trott std::extents<T2, D, D, D, D, D>(5, 7, 8, 9, 1)); 70cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, D, D, 8, 9, D>>(std::extents<T2, D, 7, 8, 9, 1>(5)); 71cfa096d9SChristian Trott test_conversion<idx_convertible && true, std::extents<T1, 5, 7, 8, 9, 1>>(std::extents<T2, 5, 7, 8, 9, 1>()); 72cfa096d9SChristian Trott // clang-format on 73cfa096d9SChristian Trott } 74cfa096d9SChristian Trott 75cfa096d9SChristian Trott template <class IdxT, size_t... Extents> 7602d513cfSStephan T. Lavavej using mapping_t = std::layout_right::mapping<std::extents<IdxT, Extents...>>; 77cfa096d9SChristian Trott 78cfa096d9SChristian Trott constexpr void test_no_implicit_conversion() { 79cfa096d9SChristian Trott constexpr size_t D = std::dynamic_extent; 80cfa096d9SChristian Trott 81cfa096d9SChristian Trott // Sanity check that one static to dynamic conversion works 82cfa096d9SChristian Trott static_assert(std::is_constructible_v<mapping_t<int, D>, mapping_t<int, 5>>); 83cfa096d9SChristian Trott static_assert(std::is_convertible_v<mapping_t<int, 5>, mapping_t<int, D>>); 84cfa096d9SChristian Trott 85cfa096d9SChristian Trott // Check that dynamic to static conversion only works explicitly 86cfa096d9SChristian Trott static_assert(std::is_constructible_v<mapping_t<int, 5>, mapping_t<int, D>>); 87cfa096d9SChristian Trott static_assert(!std::is_convertible_v<mapping_t<int, D>, mapping_t<int, 5>>); 88cfa096d9SChristian Trott 89cfa096d9SChristian Trott // Sanity check that one static to dynamic conversion works 90cfa096d9SChristian Trott static_assert(std::is_constructible_v<mapping_t<int, D, 7>, mapping_t<int, 5, 7>>); 91cfa096d9SChristian Trott static_assert(std::is_convertible_v<mapping_t<int, 5, 7>, mapping_t<int, D, 7>>); 92cfa096d9SChristian Trott 93cfa096d9SChristian Trott // Check that dynamic to static conversion only works explicitly 94cfa096d9SChristian Trott static_assert(std::is_constructible_v<mapping_t<int, 5, 7>, mapping_t<int, D, 7>>); 95cfa096d9SChristian Trott static_assert(!std::is_convertible_v<mapping_t<int, D, 7>, mapping_t<int, 5, 7>>); 96cfa096d9SChristian Trott 97cfa096d9SChristian Trott // Sanity check that smaller index_type to larger index_type conversion works 98cfa096d9SChristian Trott static_assert(std::is_constructible_v<mapping_t<size_t, 5>, mapping_t<int, 5>>); 99cfa096d9SChristian Trott static_assert(std::is_convertible_v<mapping_t<int, 5>, mapping_t<size_t, 5>>); 100cfa096d9SChristian Trott 101cfa096d9SChristian Trott // Check that larger index_type to smaller index_type conversion works explicitly only 102cfa096d9SChristian Trott static_assert(std::is_constructible_v<mapping_t<int, 5>, mapping_t<size_t, 5>>); 103cfa096d9SChristian Trott static_assert(!std::is_convertible_v<mapping_t<size_t, 5>, mapping_t<int, 5>>); 104cfa096d9SChristian Trott } 105cfa096d9SChristian Trott 106cfa096d9SChristian Trott constexpr void test_rank_mismatch() { 107cfa096d9SChristian Trott constexpr size_t D = std::dynamic_extent; 108cfa096d9SChristian Trott 109cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int, D>, mapping_t<int>>); 110cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int>, mapping_t<int, D, D>>); 111cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int, D>, mapping_t<int, D, D>>); 112cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int, D, D, D>, mapping_t<int, D, D>>); 113cfa096d9SChristian Trott } 114cfa096d9SChristian Trott 115cfa096d9SChristian Trott constexpr void test_static_extent_mismatch() { 116cfa096d9SChristian Trott constexpr size_t D = std::dynamic_extent; 117cfa096d9SChristian Trott 118cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int, D, 5>, mapping_t<int, D, 4>>); 119cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int, 5>, mapping_t<int, 4>>); 120cfa096d9SChristian Trott static_assert(!std::is_constructible_v<mapping_t<int, 5, D>, mapping_t<int, 4, D>>); 121cfa096d9SChristian Trott } 122cfa096d9SChristian Trott 123cfa096d9SChristian Trott constexpr bool test() { 124cfa096d9SChristian Trott test_conversion<int, int>(); 125cfa096d9SChristian Trott test_conversion<int, size_t>(); 126cfa096d9SChristian Trott test_conversion<size_t, int>(); 127cfa096d9SChristian Trott test_conversion<size_t, long>(); 128cfa096d9SChristian Trott test_no_implicit_conversion(); 129cfa096d9SChristian Trott test_rank_mismatch(); 130cfa096d9SChristian Trott test_static_extent_mismatch(); 131cfa096d9SChristian Trott return true; 132cfa096d9SChristian Trott } 133cfa096d9SChristian Trott 134cfa096d9SChristian Trott int main(int, char**) { 135cfa096d9SChristian Trott test(); 136cfa096d9SChristian Trott static_assert(test()); 137cfa096d9SChristian Trott return 0; 138cfa096d9SChristian Trott } 139