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

source code of libcxx/test/std/containers/views/mdspan/layout_right/ctor.layout_left.pass.cpp