2222# error "This file requires MDSPAN_ENABLE_P3663=ON"
2323#endif
2424
25+ namespace my_test {
26+
27+ template <class First , class Second >
28+ struct my_aggregate_pair {
29+ First first;
30+ Second second;
31+ };
32+
33+ // Not an aggregate, to force use of the tuple protocol.
34+ template <class First , class Second >
35+ class my_nonaggregate_pair {
36+ public:
37+ constexpr my_nonaggregate_pair (First first, Second second)
38+ : first_(first), second_(second)
39+ {}
40+
41+ template <std::size_t Index, class Self >
42+ constexpr decltype (auto ) get(this Self&& self) {
43+ if constexpr (Index == 0 ) {
44+ return self.first_ ;
45+ }
46+ else if constexpr (Index == 1 ) {
47+ return self.second_ ;
48+ }
49+ else {
50+ static_assert (false , " Invalid index" );
51+ }
52+ }
53+
54+ private:
55+ First first_;
56+ Second second_;
57+ };
58+
59+ } // namespace my_test
60+
61+ template <class First , class Second >
62+ struct std ::tuple_size<my_test::my_nonaggregate_pair<First, Second>>
63+ : std::integral_constant<std::size_t , 2 > {};
64+
65+ template <std::size_t Index, class First , class Second >
66+ struct std ::tuple_element<Index, my_test::my_nonaggregate_pair<First, Second>> {
67+ static_assert (false , " Invalid index" );
68+ };
69+
70+ template <class First , class Second >
71+ struct std ::tuple_element<0 , my_test::my_nonaggregate_pair<First, Second>> {
72+ using type = First;
73+ };
74+
75+ template <class First , class Second >
76+ struct std ::tuple_element<1 , my_test::my_nonaggregate_pair<First, Second>> {
77+ using type = Second;
78+ };
79+
2580namespace {
2681
2782template <class T >
@@ -44,6 +99,14 @@ constexpr bool slice_equal(const Left&, Kokkos::full_extent_t) {
4499 return std::is_convertible_v<Left, Kokkos::full_extent_t >;
45100}
46101
102+ template <class OffsetType , class ExtentType , class StrideType >
103+ constexpr bool slice_equal (
104+ const Kokkos::strided_slice<OffsetType, ExtentType, StrideType>& left,
105+ const Kokkos::strided_slice<OffsetType, ExtentType, StrideType>& right)
106+ {
107+ return left.offset == right.offset && left.extent == right.extent && left.stride == right.stride ;
108+ }
109+
47110template <class ExpectedResult , class InputExtents , class ... Slices>
48111void
49112test_canonicalize_slices (
@@ -92,4 +155,37 @@ TEST(CanonicalizeSlices, Rank1_integer_static) {
92155 test_canonicalize_slices (expected_slices, exts, slice0);
93156}
94157
158+ TEST (CanonicalizeSlices, Rank1_pair) {
159+ constexpr auto slice0 = std::pair{std::integral_constant<int , 7 >{}, 11 };
160+ constexpr auto expected_slices = std::tuple{Kokkos::strided_slice{
161+ .offset = std::cw<size_t (7u )>,
162+ .extent = size_t (4u ), // 11 - 7
163+ .stride = std::cw<size_t (1u )>
164+ }};
165+ constexpr auto exts = Kokkos::extents<size_t , 13 >{};
166+ test_canonicalize_slices (expected_slices, exts, slice0);
167+ }
168+
169+ TEST (CanonicalizeSlices, Rank1_aggregate_pair) {
170+ constexpr auto slice0 = my_test::my_aggregate_pair<int , int >{7 , 11 };
171+ constexpr auto expected_slices = std::tuple{Kokkos::strided_slice{
172+ .offset = size_t (7u ),
173+ .extent = (size_t (11u ) - size_t (7u )),
174+ .stride = std::cw<size_t (1u )>
175+ }};
176+ constexpr auto exts = Kokkos::extents<size_t , 13 >{};
177+ test_canonicalize_slices (expected_slices, exts, slice0);
178+ }
179+
180+ TEST (CanonicalizeSlices, Rank1_nonaggregate_pair) {
181+ constexpr auto slice0 = my_test::my_nonaggregate_pair<int , int >(7 , 11 );
182+ constexpr auto expected_slices = std::tuple{Kokkos::strided_slice{
183+ .offset = size_t (7u ),
184+ .extent = (size_t (11u ) - size_t (7u )),
185+ .stride = std::cw<size_t (1u )>
186+ }};
187+ constexpr auto exts = Kokkos::extents<size_t , 13 >{};
188+ test_canonicalize_slices (expected_slices, exts, slice0);
189+ }
190+
95191} // namespace (anonymous)
0 commit comments