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// A type M meets the layout mapping requirements if
14// - M models copyable and equality_comparable,
15// - is_nothrow_move_constructible_v<M> is true,
16// - is_nothrow_move_assignable_v<M> is true,
17// - is_nothrow_swappable_v<M> is true, and
18//
19// the following types and expressions are well-formed and have the specified semantics.
20//
21// typename M::extents_type
22// Result: A type that is a specialization of extents.
23//
24// typename M::index_type
25// Result: typename M::extents_type::index_type.
26//
27// typename M::rank_type
28// Result: typename M::extents_type::rank_type.
29//
30// typename M::layout_type
31// Result: A type MP that meets the layout mapping policy requirements ([mdspan.layout.policy.reqmts]) and for which is-mapping-of<MP, M> is true.
32//
33// m.extents()
34// Result: const typename M::extents_type&
35//
36// m(i...)
37// Result: typename M::index_type
38// Returns: A nonnegative integer less than numeric_limits<typename M::index_type>::max() and less than or equal to numeric_limits<size_t>::max().
39//
40// m(i...) == m(static_cast<typename M::index_type>(i)...)
41// Result: bool
42// Returns: true
43//
44// m.required_span_size()
45// Result: typename M::index_type
46// Returns: If the size of the multidimensional index space m.extents() is 0, then 0, else 1 plus the maximum value of m(i...) for all i.
47//
48// m.is_unique()
49// Result: bool
50// Returns: true only if for every i and j where (i != j || ...) is true, m(i...) != m(j...) is true.
51//
52// m.is_exhaustive()
53// Result: bool
54// Returns: true only if for all k in the range [0, m.required_span_size()) there exists an i such that m(i...) equals k.
55//
56// m.is_strided()
57// Result: bool
58// Returns: true only if for every rank index r of m.extents() there exists an integer
59// sr such that, for all i where (i+dr) is a multidimensional index in m.extents() ([mdspan.overview]),
60// m((i + dr)...) - m(i...) equals sr
61//
62// m.stride(r)
63// Preconditions: m.is_strided() is true.
64// Result: typename M::index_type
65// Returns: sr as defined in m.is_strided() above.
66//
67// M::is_always_unique()
68// Result: A constant expression ([expr.const]) of type bool.
69// Returns: true only if m.is_unique() is true for all possible objects m of type M.
70//
71// M::is_always_exhaustive()
72// Result: A constant expression ([expr.const]) of type bool.
73// Returns: true only if m.is_exhaustive() is true for all possible objects m of type M.
74//
75// M::is_always_strided()
76// Result: A constant expression ([expr.const]) of type bool.
77// Returns: true only if m.is_strided() is true for all possible objects m of type M.
78
79#include <mdspan>
80#include <type_traits>
81#include <concepts>
82#include <cassert>
83
84#include "test_macros.h"
85
86// Common requirements of all layout mappings
87template <class M, size_t... Idxs>
88void test_mapping_requirements(std::index_sequence<Idxs...>) {
89 using E = typename M::extents_type;
90 LIBCPP_STATIC_ASSERT(std::__mdspan_detail::__is_extents_v<E>);
91 static_assert(std::is_copy_constructible_v<M>);
92 static_assert(std::is_nothrow_move_constructible_v<M>);
93 static_assert(std::is_nothrow_move_assignable_v<M>);
94 static_assert(std::is_nothrow_swappable_v<M>);
95 ASSERT_SAME_TYPE(typename M::index_type, typename E::index_type);
96 ASSERT_SAME_TYPE(typename M::size_type, typename E::size_type);
97 ASSERT_SAME_TYPE(typename M::rank_type, typename E::rank_type);
98 ASSERT_SAME_TYPE(typename M::layout_type, std::layout_left);
99 ASSERT_SAME_TYPE(typename M::layout_type::template mapping<E>, M);
100 static_assert(std::is_same_v<decltype(std::declval<M>().extents()), const E&>);
101 static_assert(std::is_same_v<decltype(std::declval<M>()(Idxs...)), typename M::index_type>);
102 static_assert(std::is_same_v<decltype(std::declval<M>().required_span_size()), typename M::index_type>);
103 static_assert(std::is_same_v<decltype(std::declval<M>().is_unique()), bool>);
104 static_assert(std::is_same_v<decltype(std::declval<M>().is_exhaustive()), bool>);
105 static_assert(std::is_same_v<decltype(std::declval<M>().is_strided()), bool>);
106 if constexpr (E::rank() > 0)
107 static_assert(std::is_same_v<decltype(std::declval<M>().stride(0)), typename M::index_type>);
108 static_assert(std::is_same_v<decltype(M::is_always_unique()), bool>);
109 static_assert(std::is_same_v<decltype(M::is_always_exhaustive()), bool>);
110 static_assert(std::is_same_v<decltype(M::is_always_strided()), bool>);
111}
112
113template <class L, class E>
114void test_layout_mapping_requirements() {
115 using M = typename L::template mapping<E>;
116 test_mapping_requirements<M>(std::make_index_sequence<E::rank()>());
117}
118
119template <class E>
120void test_layout_mapping_left() {
121 test_layout_mapping_requirements<std::layout_left, E>();
122}
123
124int main(int, char**) {
125 constexpr size_t D = std::dynamic_extent;
126 test_layout_mapping_left<std::extents<int>>();
127 test_layout_mapping_left<std::extents<signed char, 4, 5>>();
128 test_layout_mapping_left<std::extents<unsigned, D, 4>>();
129 test_layout_mapping_left<std::extents<size_t, D, D, D, D>>();
130 return 0;
131}
132

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