From b6bc21e511f324213d7530e90a884276feaa7ee8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Feb 2026 19:58:37 +0000 Subject: [PATCH 1/5] Initial plan From ef17e314296f2ff0d199feff42a46fd749856fee Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:04:38 +0000 Subject: [PATCH 2/5] Add strided_slice updates with integral_constant_like support Co-authored-by: crtrott <9490481+crtrott@users.noreply.github.com> --- include/experimental/__p0009_bits/utility.hpp | 12 ++ .../__p2630_bits/integral_constant_like.hpp | 157 ++++++++++++++++++ .../__p2630_bits/strided_slice.hpp | 33 +++- tests/CMakeLists.txt | 1 + tests/test_strided_slice.cpp | 103 ++++++++++++ 5 files changed, 299 insertions(+), 7 deletions(-) create mode 100644 include/experimental/__p2630_bits/integral_constant_like.hpp create mode 100644 tests/test_strided_slice.cpp diff --git a/include/experimental/__p0009_bits/utility.hpp b/include/experimental/__p0009_bits/utility.hpp index 33e5d0f1..fdc2d890 100644 --- a/include/experimental/__p0009_bits/utility.hpp +++ b/include/experimental/__p0009_bits/utility.hpp @@ -14,6 +14,18 @@ namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { +// Backport of std::remove_cvref / std::remove_cvref_t (C++20) +#if (__cplusplus >= 202002L) + using std::remove_cvref_t; +#else + template + struct remove_cvref { + using type = std::remove_cv_t>; + }; + template + using remove_cvref_t = typename remove_cvref::type; +#endif // __cplusplus >= 202002L + // type alias used for rank-based tag dispatch // // this is used to enable alternatives to constexpr if when building for C++14 diff --git a/include/experimental/__p2630_bits/integral_constant_like.hpp b/include/experimental/__p2630_bits/integral_constant_like.hpp new file mode 100644 index 00000000..ab69f66a --- /dev/null +++ b/include/experimental/__p2630_bits/integral_constant_like.hpp @@ -0,0 +1,157 @@ +//@HEADER +// ************************************************************************ +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. +// See https://kokkos.org/LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//@HEADER + +#pragma once + +#include "../__p0009_bits/utility.hpp" +#include +#if defined(__cpp_lib_concepts) +# include +#endif // __cpp_lib_concepts + +// ============================================================ +// equality_comparable back-port (used only by integral_constant_like) +// ============================================================ + +#if defined(__cpp_lib_concepts) + +namespace MDSPAN_IMPL_STANDARD_NAMESPACE { + namespace detail { + template + struct is_equality_comparable : std::bool_constant> {}; + + template + struct is_equality_comparable_with : std::bool_constant> {}; + } // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#else + +#include + +namespace MDSPAN_IMPL_STANDARD_NAMESPACE { +namespace detail { + + template + struct is_equality_comparable : std::false_type {}; + + template + struct is_equality_comparable< + T, + std::void_t< + decltype(std::declval() == std::declval()), + decltype(std::declval() != std::declval()) + > + > : std::bool_constant< + std::is_convertible_v< + decltype(std::declval() == std::declval()), + bool + > && + std::is_convertible_v< + decltype(std::declval() != std::declval()), + bool + > + > {}; + + template + struct is_equality_comparable_with : std::false_type {}; + + template + struct is_equality_comparable_with< + T, U, + std::void_t< + decltype(std::declval() == std::declval()), + decltype(std::declval() != std::declval()), + decltype(std::declval() == std::declval()), + decltype(std::declval() != std::declval()) + > + > : std::bool_constant< + is_equality_comparable::value && + is_equality_comparable::value && + std::is_convertible_v< + decltype(std::declval() == std::declval()), + bool + > && + std::is_convertible_v< + decltype(std::declval() != std::declval()), + bool + > && + std::is_convertible_v< + decltype(std::declval() == std::declval()), + bool + > && + std::is_convertible_v< + decltype(std::declval() != std::declval()), + bool + > + > {}; + +} // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#endif // defined(__cpp_lib_concepts) + +// ============================================================ +// integral_constant_like concept / trait +// ============================================================ + +#if defined(__cpp_lib_concepts) + +namespace MDSPAN_IMPL_STANDARD_NAMESPACE { + namespace detail { + + template + concept integral_constant_like = + std::is_integral_v> && + !std::is_same_v> && + std::convertible_to && + std::equality_comparable_with && + std::bool_constant::value && + std::bool_constant(T()) == T::value>::value; + + template + constexpr bool is_integral_constant_like_v = integral_constant_like; + + } // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#else + +namespace MDSPAN_IMPL_STANDARD_NAMESPACE { + namespace detail { + + template + struct is_integral_constant_like_impl : std::false_type {}; + + template + struct is_integral_constant_like_impl> : + std::bool_constant< + std::is_integral_v> && + ! std::is_same_v> && + std::is_convertible_v && + is_equality_comparable_with::value && + std::bool_constant::value && + std::bool_constant(T()) == T::value>::value + > + {}; + + template + constexpr bool is_integral_constant_like_v = is_integral_constant_like_impl::value; + + } // namespace detail +} // namespace MDSPAN_IMPL_STANDARD_NAMESPACE + +#endif // __cpp_lib_concepts diff --git a/include/experimental/__p2630_bits/strided_slice.hpp b/include/experimental/__p2630_bits/strided_slice.hpp index 7f4a0188..3803d7c7 100644 --- a/include/experimental/__p2630_bits/strided_slice.hpp +++ b/include/experimental/__p2630_bits/strided_slice.hpp @@ -17,17 +17,36 @@ #pragma once +#include "../__p0009_bits/config.hpp" +#include "constant_wrapper.hpp" +#include "integral_constant_like.hpp" + #include namespace MDSPAN_IMPL_STANDARD_NAMESPACE { namespace detail { + template + struct is_signed_or_unsigned_integral_constant_like : std::false_type {}; + template - struct mdspan_is_integral_constant: std::false_type {}; + struct is_signed_or_unsigned_integral_constant_like< + T, std::enable_if_t> + > : std::bool_constant< + std::is_integral_v> && + ! std::is_same_v> + > + {}; - template - struct mdspan_is_integral_constant>: std::true_type {}; -} + template + constexpr bool is_signed_or_unsigned_integral_constant_like_v = + is_signed_or_unsigned_integral_constant_like::value; + + template + constexpr bool __mdspan_is_index_like_v = + (std::is_integral_v && ! std::is_same_v) || + is_signed_or_unsigned_integral_constant_like_v; +} // namespace detail // Slice Specifier allowing for strides and compile time extent template @@ -40,9 +59,9 @@ struct strided_slice { MDSPAN_IMPL_NO_UNIQUE_ADDRESS ExtentType extent{}; MDSPAN_IMPL_NO_UNIQUE_ADDRESS StrideType stride{}; - static_assert(std::is_integral_v || detail::mdspan_is_integral_constant::value); - static_assert(std::is_integral_v || detail::mdspan_is_integral_constant::value); - static_assert(std::is_integral_v || detail::mdspan_is_integral_constant::value); + static_assert(detail::__mdspan_is_index_like_v); + static_assert(detail::__mdspan_is_index_like_v); + static_assert(detail::__mdspan_is_index_like_v); }; } // MDSPAN_IMPL_STANDARD_NAMESPACE diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index c3abd883..1693ac65 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -113,3 +113,4 @@ endif() endif() mdspan_add_test(test_constant_wrapper) +mdspan_add_test(test_strided_slice) diff --git a/tests/test_strided_slice.cpp b/tests/test_strided_slice.cpp new file mode 100644 index 00000000..4969ae43 --- /dev/null +++ b/tests/test_strided_slice.cpp @@ -0,0 +1,103 @@ +//@HEADER +// ************************************************************************ +// +// Kokkos v. 4.0 +// Copyright (2022) National Technology & Engineering +// Solutions of Sandia, LLC (NTESS). +// +// Under the terms of Contract DE-NA0003525 with NTESS, +// the U.S. Government retains certain rights in this software. +// +// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions. +// See https://kokkos.org/LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//@HEADER +#include +#include + +#include + +namespace { + +template +void test_strided_slice(OffsetType offset, ExtentType extent, StrideType stride) +{ + // Some compilers are bad at CTAD for aggregates. + Kokkos::strided_slice s{offset, extent, stride}; + + static_assert(std::is_same_v>); + auto offset2 = s.offset; + static_assert(std::is_same_v); + auto extent2 = s.extent; + static_assert(std::is_same_v); + auto stride2 = s.stride; + static_assert(std::is_same_v); + + ASSERT_EQ(offset2, offset); + ASSERT_EQ(extent2, extent); + ASSERT_EQ(stride2, stride); +} + +template +constexpr auto IC = std::integral_constant{}; + +#if defined(MDSPAN_IMPL_ENABLE_P3663) +MDSPAN_TEMPLATE_REQUIRES( + class T, + T Value, + /* requires */ ( + std::is_integral_v && ! std::is_same_v + ) +) +struct my_integral_constant { + static constexpr T value = Value; + constexpr operator T () const { return value; } + // icpx insists that, even with the macro protection, + // "declaring overloaded 'operator()' as 'static' is a C++2b extension." +#if (__cplusplus >= 202302L) && defined(__cpp_static_call_operator) + static constexpr T operator() () { return value; } +#endif +}; + +template +constexpr auto IC2 = my_integral_constant{}; + +static_assert( + std::is_convertible_v< + my_integral_constant, + decltype(my_integral_constant::value)>); + +static_assert( + Kokkos::detail::is_equality_comparable_with< + my_integral_constant, + decltype(my_integral_constant::value)>::value); + +static_assert( + Kokkos::detail::is_integral_constant_like_v< + my_integral_constant + >); +#endif // MDSPAN_IMPL_ENABLE_P3663 + +TEST(StridedSlice, WellFormed) { + test_strided_slice(int(1), unsigned(10), long(3)); + test_strided_slice((signed char)(1), (unsigned short)(10), (unsigned long long)(3)); + + test_strided_slice(IC, unsigned(10), long(3)); + test_strided_slice(int(1), IC, long(3)); + test_strided_slice(int(1), unsigned(10), IC); + +#if defined(MDSPAN_IMPL_ENABLE_P3663) + using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; + + test_strided_slice(cw<1>, unsigned(10), long(3)); + test_strided_slice(int(1), cw, long(3)); + test_strided_slice(int(1), unsigned(10), cw); + + test_strided_slice(IC2, unsigned(10), long(3)); + test_strided_slice(int(1), IC2, long(3)); + test_strided_slice(int(1), unsigned(10), IC2); +#endif +} + +} // namespace (anonymous) From f2188f5ffd26ebd2f33aa9b7dee91ffd02d3cd0a Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 20 Feb 2026 13:08:20 -0700 Subject: [PATCH 3/5] Apply suggestions from code review --- include/experimental/__p2630_bits/strided_slice.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/experimental/__p2630_bits/strided_slice.hpp b/include/experimental/__p2630_bits/strided_slice.hpp index 3803d7c7..f1fa6d1a 100644 --- a/include/experimental/__p2630_bits/strided_slice.hpp +++ b/include/experimental/__p2630_bits/strided_slice.hpp @@ -43,7 +43,7 @@ namespace detail { is_signed_or_unsigned_integral_constant_like::value; template - constexpr bool __mdspan_is_index_like_v = + constexpr bool mdspan_is_index_like_v = (std::is_integral_v && ! std::is_same_v) || is_signed_or_unsigned_integral_constant_like_v; } // namespace detail @@ -59,9 +59,9 @@ struct strided_slice { MDSPAN_IMPL_NO_UNIQUE_ADDRESS ExtentType extent{}; MDSPAN_IMPL_NO_UNIQUE_ADDRESS StrideType stride{}; - static_assert(detail::__mdspan_is_index_like_v); - static_assert(detail::__mdspan_is_index_like_v); - static_assert(detail::__mdspan_is_index_like_v); + static_assert(detail::mdspan_is_index_like_v); + static_assert(detail::mdspan_is_index_like_v); + static_assert(detail::mdspan_is_index_like_v); }; } // MDSPAN_IMPL_STANDARD_NAMESPACE From 0489fe27def3faac1f64255f2ff3920bf9cbd835 Mon Sep 17 00:00:00 2001 From: Christian Trott Date: Fri, 20 Feb 2026 14:08:13 -0700 Subject: [PATCH 4/5] Update include/experimental/__p0009_bits/utility.hpp Co-authored-by: Mark Hoemmen --- include/experimental/__p0009_bits/utility.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/experimental/__p0009_bits/utility.hpp b/include/experimental/__p0009_bits/utility.hpp index fdc2d890..acadd6f7 100644 --- a/include/experimental/__p0009_bits/utility.hpp +++ b/include/experimental/__p0009_bits/utility.hpp @@ -19,11 +19,7 @@ namespace detail { using std::remove_cvref_t; #else template - struct remove_cvref { - using type = std::remove_cv_t>; - }; - template - using remove_cvref_t = typename remove_cvref::type; + using remove_cvref_t = std::remove_cv_t>; #endif // __cplusplus >= 202002L // type alias used for rank-based tag dispatch From 7a1c1df49a45a51909769b4f2b0a3a0ffc1a7fad Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Feb 2026 21:15:07 +0000 Subject: [PATCH 5/5] Remove MDSPAN_IMPL_ENABLE_P3663 guards and operator() block from test_strided_slice Co-authored-by: crtrott <9490481+crtrott@users.noreply.github.com> --- tests/test_strided_slice.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/test_strided_slice.cpp b/tests/test_strided_slice.cpp index 4969ae43..f16a20e0 100644 --- a/tests/test_strided_slice.cpp +++ b/tests/test_strided_slice.cpp @@ -42,7 +42,6 @@ void test_strided_slice(OffsetType offset, ExtentType extent, StrideType stride) template constexpr auto IC = std::integral_constant{}; -#if defined(MDSPAN_IMPL_ENABLE_P3663) MDSPAN_TEMPLATE_REQUIRES( class T, T Value, @@ -53,11 +52,6 @@ MDSPAN_TEMPLATE_REQUIRES( struct my_integral_constant { static constexpr T value = Value; constexpr operator T () const { return value; } - // icpx insists that, even with the macro protection, - // "declaring overloaded 'operator()' as 'static' is a C++2b extension." -#if (__cplusplus >= 202302L) && defined(__cpp_static_call_operator) - static constexpr T operator() () { return value; } -#endif }; template @@ -77,7 +71,6 @@ static_assert( Kokkos::detail::is_integral_constant_like_v< my_integral_constant >); -#endif // MDSPAN_IMPL_ENABLE_P3663 TEST(StridedSlice, WellFormed) { test_strided_slice(int(1), unsigned(10), long(3)); @@ -87,7 +80,6 @@ TEST(StridedSlice, WellFormed) { test_strided_slice(int(1), IC, long(3)); test_strided_slice(int(1), unsigned(10), IC); -#if defined(MDSPAN_IMPL_ENABLE_P3663) using MDSPAN_IMPL_STANDARD_NAMESPACE::detail::cw; test_strided_slice(cw<1>, unsigned(10), long(3)); @@ -97,7 +89,6 @@ TEST(StridedSlice, WellFormed) { test_strided_slice(IC2, unsigned(10), long(3)); test_strided_slice(int(1), IC2, long(3)); test_strided_slice(int(1), unsigned(10), IC2); -#endif } } // namespace (anonymous)