Skip to content

Incorrect submdspan with full_extent_t with g++-16 and C++26 #485

Open

Description

@masterleinad
#include <mdspan/mdspan.hpp>
#include <type_traits>
#include <utility>

using FE = Kokkos::full_extent_t;
using X = decltype(Kokkos::submdspan_extents(
    Kokkos::extents<size_t, 10, 5, 2>{}, FE{}, FE{}, FE{}));

static_assert(X::rank() == 3);
static_assert(X::static_extent(0) == 10);
static_assert(X::static_extent(1) == 5);
static_assert(X::static_extent(2) == 2);

int main() {}

fails wth g++-16 in C++26 mode with

/tmp/cmake_example.cpp:10:35: error: static assertion failed
   10 | static_assert(X::static_extent(0) == 10);
      |               ~~~~~~~~~~~~~~~~~~~~^~~~~
  • the comparison reduces to '(18446744073709551615 == 10)'
/tmp/cmake_example.cpp:11:35: error: static assertion failed
   11 | static_assert(X::static_extent(1) == 5);
      |               ~~~~~~~~~~~~~~~~~~~~^~~~
  • the comparison reduces to '(18446744073709551615 == 5)'
/tmp/cmake_example.cpp:12:35: error: static assertion failed
   12 | static_assert(X::static_extent(2) == 2);
      |               ~~~~~~~~~~~~~~~~~~~~^~~~
  • the comparison reduces to '(18446744073709551615 == 2)'

since constant_wrapper isn't derived from integral_constant anymore.
A quick fix would be

diff --git a/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp b/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp
index 429877e7d..380032786 100644
--- a/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp
+++ b/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp
@@ -170,6 +171,24 @@ struct StaticExtentFromRange<integral_constant<Integral0, val0>,
   constexpr static size_t value = val1 - val0;
 };
 
+template <class Integral0, Integral0 val0, auto val1, class Integral1>
+struct StaticExtentFromRange<integral_constant<Integral0, val0>,
+                             constant_wrapper<val1, Integral1>>
+    : StaticExtentFromRange<integral_constant<Integral0, val0>,
+                            integral_constant<Integral1, static_cast<Integral1>(val1)>> {};
+
+template <auto val0, class Integral0, class Integral1, Integral1 val1>
+struct StaticExtentFromRange<constant_wrapper<val0, Integral0>,
+                             integral_constant<Integral1, val1>>
+    : StaticExtentFromRange<integral_constant<Integral0, static_cast<Integral0>(val0)>,
+                            integral_constant<Integral1, val1>> {};
+
+template <auto val0, class Integral0, auto val1, class Integral1>
+struct StaticExtentFromRange<constant_wrapper<val0, Integral0>,
+                             constant_wrapper<val1, Integral1>>
+    : StaticExtentFromRange<integral_constant<Integral0, static_cast<Integral0>(val0)>,
+                            integral_constant<Integral1, static_cast<Integral1>(val1)>> {};
+
 // compute new static extent from strided_slice, preserving static
 // knowledge
 template <class Arg0, class Arg1> struct StaticExtentFromStridedRange {
@@ -188,6 +207,24 @@ struct StaticExtentFromStridedRange<integral_constant<Integral0, val0>,
   constexpr static size_t value = val0 > 0 ? 1 + (val0 - 1) / val1 : 0;
 };
 
+template <class Integral0, Integral0 val0, auto val1, class Integral1>
+struct StaticExtentFromStridedRange<integral_constant<Integral0, val0>,
+                                    constant_wrapper<val1, Integral1>>
+    : StaticExtentFromStridedRange<integral_constant<Integral0, val0>,
+                                   integral_constant<Integral1, static_cast<Integral1>(val1)>> {};
+
+template <auto val0, class Integral0, class Integral1, Integral1 val1>
+struct StaticExtentFromStridedRange<constant_wrapper<val0, Integral0>,
+                                    integral_constant<Integral1, val1>>
+    : StaticExtentFromStridedRange<integral_constant<Integral0, static_cast<Integral0>(val0)>,
+                                   integral_constant<Integral1, val1>> {};
+
+template <auto val0, class Integral0, auto val1, class Integral1>
+struct StaticExtentFromStridedRange<constant_wrapper<val0, Integral0>,
+                                    constant_wrapper<val1, Integral1>>
+    : StaticExtentFromStridedRange<integral_constant<Integral0, static_cast<Integral0>(val0)>,
+                                   integral_constant<Integral1, static_cast<Integral1>(val1)>> {};
+
 // creates new extents through recursive calls to next_extent member function
 // next_extent has different overloads for different types of stride specifiers
 template <size_t K, class Extents, size_t... NewExtents>

Activity

  1. masterleinad commented on Oct 16, 2026

    @masterleinad
    ContributorAuthor
    diff --git a/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp b/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp
    index 429877e7d..6b4c7c09d 100644
    --- a/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp
    +++ b/tpls/mdspan/include/experimental/__p2630_bits/submdspan_extents.hpp
    @@ -158,16 +158,11 @@ template <class Arg0, class Arg1> struct StaticExtentFromRange {
       constexpr static size_t value = dynamic_extent;
     };
     
    -template <class Integral0, Integral0 val0, class Integral1, Integral1 val1>
    -struct StaticExtentFromRange<std::integral_constant<Integral0, val0>,
    -                             std::integral_constant<Integral1, val1>> {
    -  constexpr static size_t value = val1 - val0;
    -};
    -
    -template <class Integral0, Integral0 val0, class Integral1, Integral1 val1>
    -struct StaticExtentFromRange<integral_constant<Integral0, val0>,
    -                             integral_constant<Integral1, val1>> {
    -  constexpr static size_t value = val1 - val0;
    +template <class IntegralConstantLike0, class IntegralConstantLike1>
    +requires (integral_constant_like<IntegralConstantLike0> && integral_constant_like<IntegralConstantLike0>) 
    +struct StaticExtentFromRange<IntegralConstantLike0,
    +                             IntegralConstantLike1> {
    +  constexpr static size_t value = IntegralConstantLike1::value - IntegralConstantLike0::value;
     };
     
     // compute new static extent from strided_slice, preserving static
    @@ -176,16 +171,11 @@ template <class Arg0, class Arg1> struct StaticExtentFromStridedRange {
       constexpr static size_t value = dynamic_extent;
     };
     
    -template <class Integral0, Integral0 val0, class Integral1, Integral1 val1>
    -struct StaticExtentFromStridedRange<std::integral_constant<Integral0, val0>,
    -                                    std::integral_constant<Integral1, val1>> {
    -  constexpr static size_t value = val0 > 0 ? 1 + (val0 - 1) / val1 : 0;
    -};
    -
    -template <class Integral0, Integral0 val0, class Integral1, Integral1 val1>
    -struct StaticExtentFromStridedRange<integral_constant<Integral0, val0>,
    -                                    integral_constant<Integral1, val1>> {
    -  constexpr static size_t value = val0 > 0 ? 1 + (val0 - 1) / val1 : 0;
    +template <class IntegralConstantLike0, class IntegralConstantLike1>
    +requires (integral_constant_like<IntegralConstantLike0> && integral_constant_like<IntegralConstantLike0>)   
    +struct StaticExtentFromStridedRange<IntegralConstantLike0,
    +                                   IntegralConstantLike1> {
    +  constexpr static size_t value = IntegralConstantLike0::value > 0 ? 1 + (IntegralConstantLike0::value - 1) / IntegralConstantLike1::value : 0;
     };
     
     // creates new extents through recursive calls to next_extent member function

    would also fix it.

  2. crtrott commented on Oct 16, 2026

    @crtrott
    Member

    #488 addresses this and a few other issues which popped up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions