[libc++] P2389R2: `dextents` Index Type Parameter
Introduction
This patch implements P2389R2, which was adopted at the St. Louis meeting. It builds upon previous enhancements from P2299R3, which introduced deduction guides and the dextents alias template. The main problem addressed is the increased verbosity of dextents following the parameterization of index types in P2553R1. After considering and rejecting a breaking change, the paper proposes introducing a new template alias called dims, which simplifies the declaration of mdspan with dynamic extents while maintaining the option to customize the index type.
Reference
@llvm/pr-subscribers-libcxx
Author: Xiaoyang Liu (xiaoyang-sde)
Changes
Introduction
This patch implements P2389R2, which was adopted at the St. Louis meeting. It builds upon previous enhancements from P2299R3, which introduced deduction guides and the dextents alias template. The main problem addressed is the increased verbosity of dextents following the parameterization of index types in P2553R1. After considering and rejecting a breaking change, the paper proposes introducing a new template alias called dims, which simplifies the declaration of mdspan with dynamic extents while maintaining the option to customize the index type.
Reference
Full diff: https://github.com/llvm/llvm-project/pull/97393.diff
9 Files Affected:
- (modified) libcxx/docs/FeatureTestMacroTable.rst (+2)
- (modified) libcxx/docs/ReleaseNotes/19.rst (+1)
- (modified) libcxx/include/__mdspan/extents.h (+6)
- (modified) libcxx/include/mdspan (+4)
- (modified) libcxx/include/version (+3-1)
- (added) libcxx/test/std/containers/views/mdspan/extents/dims.pass.cpp (+49)
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp (+3-3)
- (modified) libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp (+2-2)
- (modified) libcxx/utils/generate_feature_test_macro_components.py (+1-1)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 72f624fa746b4..c7cdb15a7c3e1 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -440,6 +440,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_linalg`` *unimplemented*
---------------------------------------------------------- -----------------
+ ``__cpp_lib_mdspan`` ``202406L``
+ ---------------------------------------------------------- -----------------
``__cpp_lib_out_ptr`` *unimplemented*
---------------------------------------------------------- -----------------
``__cpp_lib_ranges_concat`` *unimplemented*
diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst
index d30021b7eb234..9d36a16df74f6 100644
--- a/libcxx/docs/ReleaseNotes/19.rst
+++ b/libcxx/docs/ReleaseNotes/19.rst
@@ -53,6 +53,7 @@ Implemented Papers
- P2713R1 - Escaping improvements in ``std::format``
- P2231R1 - Missing ``constexpr`` in ``std::optional`` and ``std::variant``
- P0019R8 - ``std::atomic_ref``
+- P2389R2 - ``dextents`` Index Type Parameter
Improvements and New Features
-----------------------------
diff --git a/libcxx/include/__mdspan/extents.h b/libcxx/include/__mdspan/extents.h
index fea0decd8c6af..27d05122a11f5 100644
--- a/libcxx/include/__mdspan/extents.h
+++ b/libcxx/include/__mdspan/extents.h
@@ -465,6 +465,12 @@ template <class... _IndexTypes>
explicit extents(_IndexTypes...) -> extents<size_t, size_t(((void)sizeof(_IndexTypes), dynamic_extent))...>;
# endif
+# if _LIBCPP_STD_VER >= 26
+// [mdspan.extents.dims], alias template `dims`
+template <size_t _Rank, class _IndexType = size_t>
+using dims = dextents<_IndexType, _Rank>;
+# endif
+
namespace __mdspan_detail {
// Helper type traits for identifying a class as extents.
diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan
index 8d443f4acd1dd..aa7ba278b1aa0 100644
--- a/libcxx/include/mdspan
+++ b/libcxx/include/mdspan
@@ -20,6 +20,10 @@ namespace std {
template<class IndexType, size_t Rank>
using dextents = see below;
+ // [mdspan.extents.dims], alias template dims
+ template<size_t Rank, class IndexType = size_t>
+ using dims = see below; // since C++26
+
// [mdspan.layout], layout mapping
struct layout_left;
struct layout_right;
diff --git a/libcxx/include/version b/libcxx/include/version
index cac6eaa3b6e88..c8ea46127db82 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -156,7 +156,7 @@ __cpp_lib_make_unique 201304L <memory>
__cpp_lib_map_try_emplace 201411L <map>
__cpp_lib_math_constants 201907L <numbers>
__cpp_lib_math_special_functions 201603L <cmath>
-__cpp_lib_mdspan 202207L <mdspan>
+__cpp_lib_mdspan 202406L <mdspan>
__cpp_lib_memory_resource 201603L <memory_resource>
__cpp_lib_move_iterator_concept 202207L <iterator>
__cpp_lib_move_only_function 202110L <functional>
@@ -521,6 +521,8 @@ __cpp_lib_void_t 201411L <type_traits>
// # define __cpp_lib_hazard_pointer 202306L
// # define __cpp_lib_is_within_lifetime 202306L
// # define __cpp_lib_linalg 202311L
+# undef __cpp_lib_mdspan
+# define __cpp_lib_mdspan 202406L
# undef __cpp_lib_out_ptr
// # define __cpp_lib_out_ptr 202311L
// # define __cpp_lib_ranges_concat 202403L
diff --git a/libcxx/test/std/containers/views/mdspan/extents/dims.pass.cpp b/libcxx/test/std/containers/views/mdspan/extents/dims.pass.cpp
new file mode 100644
index 0000000000000..e74bc0e66fca1
--- /dev/null
+++ b/libcxx/test/std/containers/views/mdspan/extents/dims.pass.cpp
@@ -0,0 +1,49 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++23
+
+// <mdspan>
+
+// template<size_t Rank, class IndexType = size_t>
+// using dims = see below;
+//
+// Result: A type E that is a specialization of extents such that
+// E::rank() == Rank && E::rank() == E::rank_dynamic() is true,
+// and E::index_type denotes IndexType.
+
+#include <mdspan>
+#include <cstddef>
+
+#include "test_macros.h"
+
+template <class IndexType>
+void test_alias_template_dims() {
+ constexpr size_t D = std::dynamic_extent;
+ ASSERT_SAME_TYPE(std::dims<0, IndexType>, std::extents<IndexType>);
+ ASSERT_SAME_TYPE(std::dims<1, IndexType>, std::extents<IndexType, D>);
+ ASSERT_SAME_TYPE(std::dims<2, IndexType>, std::extents<IndexType, D, D>);
+ ASSERT_SAME_TYPE(std::dims<3, IndexType>, std::extents<IndexType, D, D, D>);
+ ASSERT_SAME_TYPE(std::dims<9, IndexType>, std::extents<IndexType, D, D, D, D, D, D, D, D, D>);
+}
+
+template <>
+void test_alias_template_dims<size_t>() {
+ constexpr size_t D = std::dynamic_extent;
+ ASSERT_SAME_TYPE(std::dims<0>, std::extents<size_t>);
+ ASSERT_SAME_TYPE(std::dims<1>, std::extents<size_t, D>);
+ ASSERT_SAME_TYPE(std::dims<2>, std::extents<size_t, D, D>);
+ ASSERT_SAME_TYPE(std::dims<3>, std::extents<size_t, D, D, D>);
+ ASSERT_SAME_TYPE(std::dims<9>, std::extents<size_t, D, D, D, D, D, D, D, D, D>);
+}
+
+int main(int, char**) {
+ test_alias_template_dims<int>();
+ test_alias_template_dims<unsigned int>();
+ test_alias_template_dims<size_t>();
+ return 0;
+}
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp
index 4ef3382306421..bd92562d31186 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/mdspan.version.compile.pass.cpp
@@ -17,7 +17,7 @@
/* Constant Value
__cpp_lib_freestanding_mdspan 202311L [C++26]
- __cpp_lib_mdspan 202207L [C++23]
+ __cpp_lib_mdspan 202406L [C++26]
__cpp_lib_submdspan 202306L [C++26]
*/
@@ -115,8 +115,8 @@
# ifndef __cpp_lib_mdspan
# error "__cpp_lib_mdspan should be defined in c++26"
# endif
-# if __cpp_lib_mdspan != 202207L
-# error "__cpp_lib_mdspan should have the value 202207L in c++26"
+# if __cpp_lib_mdspan != 202406L
+# error "__cpp_lib_mdspan should have the value 202406L in c++26"
# endif
# if !defined(_LIBCPP_VERSION)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 32ed30e21cbbe..2a72ce97c1fbc 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -143,7 +143,7 @@
__cpp_lib_map_try_emplace 201411L [C++17]
__cpp_lib_math_constants 201907L [C++20]
__cpp_lib_math_special_functions 201603L [C++17]
- __cpp_lib_mdspan 202207L [C++23]
+ __cpp_lib_mdspan 202406L [C++26]
__cpp_lib_memory_resource 201603L [C++17]
__cpp_lib_modules 202207L [C++23]
__cpp_lib_move_iterator_concept 202207L [C++20]
@@ -7160,7 +7160,7 @@
# ifndef __cpp_lib_mdspan
# error "__cpp_lib_mdspan should be defined in c++26"
# endif
-# if __cpp_lib_mdspan != 202207L
+# if __cpp_lib_mdspan != 202406L
# error "__cpp_lib_mdspan should have the value 202207L in c++26"
# endif
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index fe5bab05195a3..89cba7169e94b 100755
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -848,7 +848,7 @@ def add_version_header(tc):
},
{
"name": "__cpp_lib_mdspan",
- "values": {"c++23": 202207},
+ "values": {"c++23": 202207, "c++26": 202406},
"headers": ["mdspan"],
},
{
I've just committed https://github.com/llvm/llvm-project/pull/97951 can you rebase your patch on main and update the status page for this patch.
Rebased and updated the status page. This can be merged once the CI is green.
:white_check_mark: With the latest revision this PR passed the Python code formatter.