File: ctor.mapping.pass.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 1,998,492 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (136 lines) | stat: -rw-r--r-- 5,698 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//===----------------------------------------------------------------------===//
//
// 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

// <mdspan>

// template<class OtherExtents>
//   constexpr explicit(!is_convertible_v<OtherExtents, extents_type>)
//     mapping(const mapping<OtherExtents>&) noexcept;

// Constraints: is_constructible_v<extents_type, OtherExtents> is true.
//
// Preconditions: other.required_span_size() is representable as a value of type index_type

#include <mdspan>
#include <type_traits>
#include <cassert>
#include <limits>

#include "test_macros.h"

template <class To, class From>
constexpr void test_implicit_conversion(To dest, From src) {
  assert(dest == src);
}

template <bool implicit, class ToE, class FromE>
constexpr void test_conversion(FromE src_exts) {
  using To   = std::layout_left::mapping<ToE>;
  using From = std::layout_left::mapping<FromE>;
  From src(src_exts);

  ASSERT_NOEXCEPT(To(src));
  To dest(src);

  assert(dest == src);
  if constexpr (implicit) {
    dest = src;
    assert(dest == src);
    test_implicit_conversion<To, From>(src, src);
  }
}

template <class T1, class T2>
constexpr void test_conversion() {
  constexpr size_t D = std::dynamic_extent;
  constexpr bool idx_convertible =
      static_cast<size_t>(std::numeric_limits<T1>::max()) >= static_cast<size_t>(std::numeric_limits<T2>::max());

  // clang-format off
  test_conversion<idx_convertible && true,  std::extents<T1>>(std::extents<T2>());
  test_conversion<idx_convertible && true,  std::extents<T1, D>>(std::extents<T2, D>(5));
  test_conversion<idx_convertible && false, std::extents<T1, 5>>(std::extents<T2, D>(5));
  test_conversion<idx_convertible && true,  std::extents<T1, 5>>(std::extents<T2, 5>());
  test_conversion<idx_convertible && false, std::extents<T1, 5, D>>(std::extents<T2, D, D>(5, 5));
  test_conversion<idx_convertible && true,  std::extents<T1, D, D>>(std::extents<T2, D, D>(5, 5));
  test_conversion<idx_convertible && true,  std::extents<T1, D, D>>(std::extents<T2, D, 7>(5));
  test_conversion<idx_convertible && true,  std::extents<T1, 5, 7>>(std::extents<T2, 5, 7>());
  test_conversion<idx_convertible && false, std::extents<T1, 5, D, 8, D, D>>(std::extents<T2, D, D, 8, 9, 1>(5, 7));
  test_conversion<idx_convertible && true,  std::extents<T1, D, D, D, D, D>>(
                                            std::extents<T2, D, D, D, D, D>(5, 7, 8, 9, 1));
  test_conversion<idx_convertible && true,  std::extents<T1, D, D, 8, 9, D>>(std::extents<T2, D, 7, 8, 9, 1>(5));
  test_conversion<idx_convertible && true,  std::extents<T1, 5, 7, 8, 9, 1>>(std::extents<T2, 5, 7, 8, 9, 1>());
  // clang-format on
}

template <class IdxT, size_t... Extents>
using mapping_t = std::layout_left::mapping<std::extents<IdxT, Extents...>>;

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<mapping_t<int, D>, mapping_t<int, 5>>);
  static_assert(std::is_convertible_v<mapping_t<int, 5>, mapping_t<int, D>>);

  // Check that dynamic to static conversion only works explicitly
  static_assert(std::is_constructible_v<mapping_t<int, 5>, mapping_t<int, D>>);
  static_assert(!std::is_convertible_v<mapping_t<int, D>, mapping_t<int, 5>>);

  // Sanity check that one static to dynamic conversion works
  static_assert(std::is_constructible_v<mapping_t<int, D, 7>, mapping_t<int, 5, 7>>);
  static_assert(std::is_convertible_v<mapping_t<int, 5, 7>, mapping_t<int, D, 7>>);

  // Check that dynamic to static conversion only works explicitly
  static_assert(std::is_constructible_v<mapping_t<int, 5, 7>, mapping_t<int, D, 7>>);
  static_assert(!std::is_convertible_v<mapping_t<int, D, 7>, mapping_t<int, 5, 7>>);

  // Sanity check that smaller index_type to larger index_type conversion works
  static_assert(std::is_constructible_v<mapping_t<size_t, 5>, mapping_t<int, 5>>);
  static_assert(std::is_convertible_v<mapping_t<int, 5>, mapping_t<size_t, 5>>);

  // Check that larger index_type to smaller index_type conversion works explicitly only
  static_assert(std::is_constructible_v<mapping_t<int, 5>, mapping_t<size_t, 5>>);
  static_assert(!std::is_convertible_v<mapping_t<size_t, 5>, mapping_t<int, 5>>);
}

constexpr void test_rank_mismatch() {
  constexpr size_t D = std::dynamic_extent;

  static_assert(!std::is_constructible_v<mapping_t<int, D>, mapping_t<int>>);
  static_assert(!std::is_constructible_v<mapping_t<int>, mapping_t<int, D, D>>);
  static_assert(!std::is_constructible_v<mapping_t<int, D>, mapping_t<int, D, D>>);
  static_assert(!std::is_constructible_v<mapping_t<int, D, D, D>, mapping_t<int, D, D>>);
}

constexpr void test_static_extent_mismatch() {
  constexpr size_t D = std::dynamic_extent;

  static_assert(!std::is_constructible_v<mapping_t<int, D, 5>, mapping_t<int, D, 4>>);
  static_assert(!std::is_constructible_v<mapping_t<int, 5>, mapping_t<int, 4>>);
  static_assert(!std::is_constructible_v<mapping_t<int, 5, D>, mapping_t<int, 4, D>>);
}

constexpr bool test() {
  test_conversion<int, int>();
  test_conversion<int, size_t>();
  test_conversion<size_t, int>();
  test_conversion<size_t, long>();
  test_no_implicit_conversion();
  test_rank_mismatch();
  test_static_extent_mismatch();
  return true;
}

int main(int, char**) {
  test();
  static_assert(test());
  return 0;
}