[PATCH] libstdc++: implement P3052R2 view_interface::at()
Yuao Ma
addr2line@gmail.com
Thu Sep 17 13:15:34 GMT 2026
Hi all,
This patch implements the C++29 paper P3052R2, which adds _at_ to
view_interface. The implementation is straightforward and similar to
span::at.
Built and tested on x86_64-linux, ok for trunk?
Thanks,
Yuao
-------------- next part --------------
From 86863536e710326226596a98a79054626a0ab783 Mon Sep 17 00:00:00 2001
From: Yuao Ma <c8ef@outlook.com>
Date: Thu, 17 Sep 2026 21:10:39 +0800
Subject: [PATCH] libstdc++: implement P3052R2 view_interface::at()
libstdc++-v3/ChangeLog:
* include/bits/ranges_util.h (view_interface::at): Define.
* include/bits/version.def: Define view_interface.
* include/bits/version.h: Regenerate.
* testsuite/std/ranges/p3052.cc: New test.
---
libstdc++-v3/include/bits/ranges_util.h | 27 +++++++++++
libstdc++-v3/include/bits/version.def | 8 ++++
libstdc++-v3/include/bits/version.h | 10 ++++
libstdc++-v3/testsuite/std/ranges/p3052.cc | 53 ++++++++++++++++++++++
4 files changed, 98 insertions(+)
create mode 100644 libstdc++-v3/testsuite/std/ranges/p3052.cc
diff --git a/libstdc++-v3/include/bits/ranges_util.h b/libstdc++-v3/include/bits/ranges_util.h
index 423767f00fc..ae803461801 100644
--- a/libstdc++-v3/include/bits/ranges_util.h
+++ b/libstdc++-v3/include/bits/ranges_util.h
@@ -39,6 +39,13 @@
# include <bits/stl_pair.h> // __pair_like, __is_tuple_like_v
#endif
+#define __glibcxx_want_view_interface
+#include <bits/version.h>
+
+#if __cpp_lib_view_interface // >= C++29
+# include <bits/stdexcept_throw.h>
+#endif
+
#ifdef __glibcxx_ranges
namespace std _GLIBCXX_VISIBILITY(default)
{
@@ -199,6 +206,26 @@ namespace ranges
operator[](range_difference_t<_Range> __n) const
{ return ranges::begin(_M_derived())[__n]; }
+#if __cpp_lib_view_interface // >= C++29
+ template<random_access_range _Range = _Derived>
+ constexpr decltype(auto)
+ at(range_difference_t<_Range> __n) requires sized_range<_Range>
+ {
+ if (__n < 0 || __n >= ranges::distance(_M_derived()))
+ std::__throw_out_of_range("view_interface::at");
+ return (*this)[__n];
+ }
+
+ template<random_access_range _Range = const _Derived>
+ constexpr decltype(auto)
+ at(range_difference_t<_Range> __n) const requires sized_range<_Range>
+ {
+ if (__n < 0 || __n >= ranges::distance(_M_derived()))
+ std::__throw_out_of_range("view_interface::at");
+ return (*this)[__n];
+ }
+#endif
+
#if __cplusplus > 202002L
constexpr auto
cbegin() requires input_range<_Derived>
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 9c523581c65..17589685f90 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2164,6 +2164,14 @@ ftms = {
};
};
+ftms = {
+ name = view_interface;
+ values = {
+ v = 202606;
+ cxxmin = 29;
+ };
+};
+
ftms = {
name = observable_checkpoint;
values = {
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index e0003054af6..4df6a648323 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2391,6 +2391,16 @@
#endif /* !defined(__cpp_lib_unreachable) */
#undef __glibcxx_want_unreachable
+#if !defined(__cpp_lib_view_interface)
+# if (__cplusplus > 202603L)
+# define __glibcxx_view_interface 202606L
+# if defined(__glibcxx_want_all) || defined(__glibcxx_want_view_interface)
+# define __cpp_lib_view_interface 202606L
+# endif
+# endif
+#endif /* !defined(__cpp_lib_view_interface) */
+#undef __glibcxx_want_view_interface
+
#if !defined(__cpp_lib_observable_checkpoint)
# if (__cplusplus > 202302L) && (__has_builtin(__builtin_observable_checkpoint))
# define __glibcxx_observable_checkpoint 202506L
diff --git a/libstdc++-v3/testsuite/std/ranges/p3052.cc b/libstdc++-v3/testsuite/std/ranges/p3052.cc
new file mode 100644
index 00000000000..433a37dc5df
--- /dev/null
+++ b/libstdc++-v3/testsuite/std/ranges/p3052.cc
@@ -0,0 +1,53 @@
+// { dg-do run { target c++29 } }
+
+#include <testsuite_hooks.h>
+
+#include <ranges>
+#include <stdexcept>
+
+struct v1 : std::ranges::view_interface<v1> {
+ int* ptr;
+ std::size_t sz;
+
+ constexpr v1(int* p, std::size_t n) : ptr(p), sz(n) {}
+
+ constexpr int* begin() const noexcept { return ptr; }
+ constexpr int* end() const noexcept { return ptr + sz; }
+};
+
+void test01() {
+ int x[2]{0, 1};
+ v1 v(x, 2);
+ VERIFY(v.at(1) == 1);
+ v.at(1) = 3;
+ VERIFY(v.at(1) == 3);
+ VERIFY(static_cast<const v1&>(v).at(1) == 3);
+
+#if __cpp_exceptions
+ try {
+ v.at(-1);
+ VERIFY(false);
+ } catch (const std::out_of_range&) {
+ VERIFY(true);
+ } catch (...) {
+ VERIFY(false);
+ }
+
+ try {
+ v.at(2);
+ VERIFY(false);
+ } catch (const std::out_of_range&) {
+ VERIFY(true);
+ } catch (...) {
+ VERIFY(false);
+ }
+#endif
+}
+
+int main() {
+ test01();
+
+#if __cpp_lib_view_interface != 202606L
+#error "Feature-test macro __cpp_lib_view_interface has wrong value in <ranges>"
+#endif
+}
--
2.54.0
More information about the Libstdc++
mailing list