[libcxx-commits] [libcxx] [libc++][ranges] P3052R2: `view_interface::at()` (PR #205012)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Aug 27 10:56:33 PDT 2026
https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/205012
>From b868e5e71f1cca8374170bcc4cf60789344edaab Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Sun, 21 Jun 2026 23:52:40 +0300
Subject: [PATCH 1/8] [libc++][ranges] P3052R2: `view_interface::at()`
Closes #204395
Implements https://wg21.link/P3052R2
---
libcxx/docs/FeatureTestMacroTable.rst | 2 +
libcxx/docs/Status/Cxx29Papers.csv | 2 +-
libcxx/include/__ranges/view_interface.h | 26 +++
libcxx/include/version | 2 +
.../view.interface/nodiscard.verify.cpp | 7 +
.../test/libcxx/transitive_includes/cxx23.csv | 1 +
.../test/libcxx/transitive_includes/cxx26.csv | 1 +
.../ranges.version.compile.pass.cpp | 33 ++++
.../version.version.compile.pass.cpp | 33 ++++
.../view.interface/view.interface.pass.cpp | 149 ++++++++++++------
.../generate_feature_test_macro_components.py | 7 +
11 files changed, 214 insertions(+), 49 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 6bf2f35fb4212..82d0910a7d7e1 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -308,6 +308,8 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202106L``
---------------------------------------------------------- -----------------
+ ``__cpp_lib_view_interface`` ``202606L``
+ ---------------------------------------------------------- -----------------
**C++23**
----------------------------------------------------------------------------
``__cpp_lib_adaptor_iterator_pair_constructor`` ``202106L``
diff --git a/libcxx/docs/Status/Cxx29Papers.csv b/libcxx/docs/Status/Cxx29Papers.csv
index 3c48fe89be33d..656eaf5df44df 100644
--- a/libcxx/docs/Status/Cxx29Papers.csv
+++ b/libcxx/docs/Status/Cxx29Papers.csv
@@ -4,7 +4,7 @@
"`P2414R12 <https://wg21.link/P2414R12>`__","Pointer lifetime-end zap proposed solutions","2026-06 (Brno)","","","`#204392 <https://github.com/llvm/llvm-project/issues/204392>`__","Voted as a Defect Report."
"`P3319R6 <https://wg21.link/P3319R6>`__","Add an ``iota`` object for ``simd`` (and more)","2026-06 (Brno)","","","`#204393 <https://github.com/llvm/llvm-project/issues/204393>`__",""
"`P3798R1 <https://wg21.link/P3798R1>`__","The unexpected in ``std::expected``","2026-06 (Brno)","","","`#204394 <https://github.com/llvm/llvm-project/issues/204394>`__",""
-"`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","","","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
+"`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","|Complete|","23","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","Applied as a Defect Report."
"`P3395R6 <https://wg21.link/P3395R6>`__","Fix encoding issues and add a formatter for ``std::error_code``","2026-06 (Brno)","","","`#204396 <https://github.com/llvm/llvm-project/issues/204396>`__",""
"`P3505R4 <https://wg21.link/P3505R4>`__","Fix the default floating-point representation in ``std::format``","2026-06 (Brno)","","","`#204397 <https://github.com/llvm/llvm-project/issues/204397>`__","To be applied as a Defect Report."
diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h
index 96508c2be7277..c5875d024840e 100644
--- a/libcxx/include/__ranges/view_interface.h
+++ b/libcxx/include/__ranges/view_interface.h
@@ -15,6 +15,7 @@
#include <__concepts/same_as.h>
#include <__config>
#include <__iterator/concepts.h>
+#include <__iterator/distance.h>
#include <__iterator/iterator_traits.h>
#include <__iterator/prev.h>
#include <__memory/pointer_traits.h>
@@ -25,6 +26,7 @@
#include <__type_traits/is_class.h>
#include <__type_traits/make_unsigned.h>
#include <__type_traits/remove_cv.h>
+#include <stdexcept>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -159,8 +161,32 @@ class view_interface {
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr decltype(auto) operator[](range_difference_t<_RARange> __index) const {
return ranges::begin(__derived())[__index];
}
+
+ #if _LIBCPP_STD_VER >= 29
+
+ template <random_access_range _RARange = _Derived>
+ requires sized_range<_RARange> // freestanding-deleted
+ [[nodiscard]] constexpr decltype(auto) at(range_difference_t<_RARange> __index) {
+ if (__index < 0 || __index >= ranges::distance(__derived())) {
+ std::__throw_out_of_range(
+ "Precondition `0 <= __index < distance()` not satisfied. `.at(__index)` called with out-of-bounds index.");
+ }
+ return (*this)[__index];
+ }
+
+ template <random_access_range _RARange = const _Derived>
+ requires sized_range<_RARange> // freestanding-deleted
+ [[nodiscard]] constexpr decltype(auto) at(range_difference_t<_RARange> __index) const {
+ if (__index < 0 || __index >= ranges::distance(__derived())) {
+ std::__throw_out_of_range(
+ "Precondition `0 <= __index < distance()` not satisfied. `.at(__index)` called with out-of-bounds index.");
+ }
+ return (*this)[__index];
+ }
};
+#endif // _LIBCPP_STD_VER >= 29
+
} // namespace ranges
_LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/version b/libcxx/include/version
index 4a6b01093641d..94185b7602f64 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -290,6 +290,7 @@ __cpp_lib_unwrap_ref 201811L <functional>
__cpp_lib_variant 202306L <variant>
202106L // C++20
202102L // C++17
+__cpp_lib_view_interface 202606L <ranges>
__cpp_lib_void_t 201411L <type_traits>
*/
@@ -488,6 +489,7 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_unwrap_ref 201811L
# undef __cpp_lib_variant
# define __cpp_lib_variant 202106L
+# define __cpp_lib_view_interface 202606L
#endif
#if _LIBCPP_STD_VER >= 23
diff --git a/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
index a22c03f5d1a71..2bccc170aa727 100644
--- a/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
@@ -67,4 +67,11 @@ void test() {
v[Diff{0}];
// expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
std::as_const(v)[Diff{0}];
+
+#if TEST_STD_VER >= 29
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ v.at(Diff{0});
+ // expected-warning at +1 {{ignoring return value of function declared with 'nodiscard' attribute}}
+ std::as_const(v).at(Diff{0});
+#endif
}
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 53ae6c9b4e591..260c410680e39 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -11,6 +11,7 @@ algorithm iosfwd
algorithm limits
algorithm optional
algorithm ratio
+algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index f712f36caa9fc..6cc4737bff91b 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -11,6 +11,7 @@ algorithm iosfwd
algorithm limits
algorithm optional
algorithm ratio
+algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index 670b0e664721a..f42c7ede894b5 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -80,6 +80,10 @@
# error "__cpp_lib_ranges_zip should not be defined before c++23"
# endif
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++20"
+# endif
+
#elif TEST_STD_VER == 14
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -142,6 +146,10 @@
# error "__cpp_lib_ranges_zip should not be defined before c++23"
# endif
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++20"
+# endif
+
#elif TEST_STD_VER == 17
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -204,6 +212,10 @@
# error "__cpp_lib_ranges_zip should not be defined before c++23"
# endif
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++20"
+# endif
+
#elif TEST_STD_VER == 20
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -269,6 +281,13 @@
# error "__cpp_lib_ranges_zip should not be defined before c++23"
# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++20"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++20"
+# endif
+
#elif TEST_STD_VER == 23
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -385,6 +404,13 @@
# error "__cpp_lib_ranges_zip should have the value 202110L in c++23"
# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++23"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++23"
+# endif
+
#elif TEST_STD_VER > 23
# if !defined(_LIBCPP_VERSION)
@@ -516,6 +542,13 @@
# error "__cpp_lib_ranges_zip should have the value 202110L in c++26"
# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++26"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++26"
+# endif
+
#endif // TEST_STD_VER > 23
// clang-format on
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 f2d74cc99d864..79e61725a93fc 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
@@ -948,6 +948,10 @@
# error "__cpp_lib_variant should not be defined before c++17"
# endif
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++20"
+# endif
+
# ifdef __cpp_lib_void_t
# error "__cpp_lib_void_t should not be defined before c++17"
# endif
@@ -1954,6 +1958,10 @@
# error "__cpp_lib_variant should not be defined before c++17"
# endif
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++20"
+# endif
+
# ifdef __cpp_lib_void_t
# error "__cpp_lib_void_t should not be defined before c++17"
# endif
@@ -3149,6 +3157,10 @@
# error "__cpp_lib_variant should have the value 202102L in c++17"
# endif
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++20"
+# endif
+
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++17"
# endif
@@ -4611,6 +4623,13 @@
# error "__cpp_lib_variant should have the value 202106L in c++20"
# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++20"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++20"
+# endif
+
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++20"
# endif
@@ -6301,6 +6320,13 @@
# error "__cpp_lib_variant should have the value 202106L in c++23"
# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++23"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++23"
+# endif
+
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++23"
# endif
@@ -8324,6 +8350,13 @@
# error "__cpp_lib_variant should have the value 202306L in c++26"
# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++26"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++26"
+# endif
+
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++26"
# endif
diff --git a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
index bce13c38f2dab..047755b0dbb9e 100644
--- a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
@@ -21,17 +21,17 @@
#include "test_macros.h"
#include "test_iterators.h"
-template<class T>
+template <class T>
concept ValidViewInterfaceType = requires { typename std::ranges::view_interface<T>; };
-struct Empty { };
+struct Empty {};
static_assert(!ValidViewInterfaceType<void>);
static_assert(!ValidViewInterfaceType<void*>);
static_assert(!ValidViewInterfaceType<Empty*>);
static_assert(!ValidViewInterfaceType<Empty const>);
-static_assert(!ValidViewInterfaceType<Empty &>);
-static_assert( ValidViewInterfaceType<Empty>);
+static_assert(!ValidViewInterfaceType<Empty&>);
+static_assert(ValidViewInterfaceType<Empty>);
using InputIter = cpp20_input_iterator<const int*>;
@@ -50,8 +50,8 @@ struct SizedInputRange : std::ranges::view_interface<SizedInputRange> {
static_assert(std::ranges::sized_range<SizedInputRange>);
struct NotSizedSentinel {
- using value_type = int;
- using difference_type = std::ptrdiff_t;
+ using value_type = int;
+ using difference_type = std::ptrdiff_t;
using iterator_concept = std::forward_iterator_tag;
explicit NotSizedSentinel() = default;
@@ -66,9 +66,7 @@ static_assert(std::forward_iterator<NotSizedSentinel>);
using ForwardIter = forward_iterator<int*>;
// So that we conform to sized_sentinel_for.
-constexpr std::ptrdiff_t operator-(const ForwardIter& x, const ForwardIter& y) {
- return base(x) - base(y);
-}
+constexpr std::ptrdiff_t operator-(const ForwardIter& x, const ForwardIter& y) { return base(x) - base(y); }
struct ForwardRange : std::ranges::view_interface<ForwardRange> {
int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
@@ -78,19 +76,17 @@ struct ForwardRange : std::ranges::view_interface<ForwardRange> {
static_assert(std::ranges::view<ForwardRange>);
struct MoveOnlyForwardRange : std::ranges::view_interface<MoveOnlyForwardRange> {
- int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
- MoveOnlyForwardRange(MoveOnlyForwardRange const&) = delete;
- MoveOnlyForwardRange(MoveOnlyForwardRange &&) = default;
- MoveOnlyForwardRange& operator=(MoveOnlyForwardRange &&) = default;
- MoveOnlyForwardRange() = default;
+ int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+ MoveOnlyForwardRange(MoveOnlyForwardRange const&) = delete;
+ MoveOnlyForwardRange(MoveOnlyForwardRange&&) = default;
+ MoveOnlyForwardRange& operator=(MoveOnlyForwardRange&&) = default;
+ MoveOnlyForwardRange() = default;
constexpr ForwardIter begin() const { return ForwardIter(const_cast<int*>(buff)); }
constexpr ForwardIter end() const { return ForwardIter(const_cast<int*>(buff) + 8); }
};
static_assert(std::ranges::view<MoveOnlyForwardRange>);
-struct MI : std::ranges::view_interface<InputRange>,
- std::ranges::view_interface<MoveOnlyForwardRange> {
-};
+struct MI : std::ranges::view_interface<InputRange>, std::ranges::view_interface<MoveOnlyForwardRange> {};
static_assert(!std::ranges::view<MI>);
struct EmptyIsTrue : std::ranges::view_interface<EmptyIsTrue> {
@@ -131,7 +127,7 @@ struct DataIsNull : std::ranges::view_interface<DataIsNull> {
int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
constexpr ContIter begin() const { return ContIter(buff); }
constexpr ContIter end() const { return ContIter(buff + 8); }
- constexpr const int *data() const { return nullptr; }
+ constexpr const int* data() const { return nullptr; }
};
static_assert(std::ranges::view<DataIsNull>);
@@ -142,13 +138,21 @@ struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleCo
};
struct SentinelType {
- int *base_;
+ int* base_;
explicit SentinelType() = default;
- constexpr explicit SentinelType(int *base) : base_(base) {}
- friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) == sent.base_}; }
- friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) == sent.base_}; }
- friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept { return {base(iter) != sent.base_}; }
- friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept { return {base(iter) != sent.base_}; }
+ constexpr explicit SentinelType(int* base) : base_(base) {}
+ friend constexpr ResultType operator==(ForwardIter const& iter, SentinelType const& sent) noexcept {
+ return {base(iter) == sent.base_};
+ }
+ friend constexpr ResultType operator==(SentinelType const& sent, ForwardIter const& iter) noexcept {
+ return {base(iter) == sent.base_};
+ }
+ friend constexpr ResultType operator!=(ForwardIter const& iter, SentinelType const& sent) noexcept {
+ return {base(iter) != sent.base_};
+ }
+ friend constexpr ResultType operator!=(SentinelType const& sent, ForwardIter const& iter) noexcept {
+ return {base(iter) != sent.base_};
+ }
};
int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
@@ -157,21 +161,21 @@ struct BoolConvertibleComparison : std::ranges::view_interface<BoolConvertibleCo
};
static_assert(std::ranges::view<BoolConvertibleComparison>);
-template<class T>
-concept EmptyInvocable = requires (T const& obj) { obj.empty(); };
+template <class T>
+concept EmptyInvocable = requires(T const& obj) { obj.empty(); };
-template<class T>
-concept BoolOpInvocable = requires (T const& obj) { bool(obj); };
+template <class T>
+concept BoolOpInvocable = requires(T const& obj) { bool(obj); };
constexpr bool testEmpty() {
static_assert(!EmptyInvocable<InputRange>);
// LWG 3715: `view_interface::empty` is overconstrained
static_assert(EmptyInvocable<SizedInputRange>);
- static_assert( EmptyInvocable<ForwardRange>);
+ static_assert(EmptyInvocable<ForwardRange>);
static_assert(!BoolOpInvocable<InputRange>);
static_assert(BoolOpInvocable<SizedInputRange>);
- static_assert( BoolOpInvocable<ForwardRange>);
+ static_assert(BoolOpInvocable<ForwardRange>);
SizedInputRange sizedInputRange;
assert(!sizedInputRange.empty());
@@ -224,12 +228,12 @@ constexpr bool testEmpty() {
return true;
}
-template<class T>
-concept DataInvocable = requires (T const& obj) { obj.data(); };
+template <class T>
+concept DataInvocable = requires(T const& obj) { obj.data(); };
constexpr bool testData() {
static_assert(!DataInvocable<ForwardRange>);
- static_assert( DataInvocable<ContRange>);
+ static_assert(DataInvocable<ContRange>);
ContRange contiguous;
assert(contiguous.data() == contiguous.buff);
@@ -249,18 +253,18 @@ constexpr bool testData() {
return true;
}
-template<class T>
-concept SizeInvocable = requires (T const& obj) { obj.size(); };
+template <class T>
+concept SizeInvocable = requires(T const& obj) { obj.size(); };
constexpr bool testSize() {
static_assert(!SizeInvocable<InputRange>);
static_assert(!SizeInvocable<NotSizedSentinel>);
- static_assert( SizeInvocable<ForwardRange>);
+ static_assert(SizeInvocable<ForwardRange>);
// Test the test.
static_assert(std::same_as<decltype(std::declval<ForwardIter>() - std::declval<ForwardIter>()), std::ptrdiff_t>);
using UnsignedSize = std::make_unsigned_t<std::ptrdiff_t>;
- using SignedSize = std::common_type_t<std::ptrdiff_t, std::make_signed_t<UnsignedSize>>;
+ using SignedSize = std::common_type_t<std::ptrdiff_t, std::make_signed_t<UnsignedSize>>;
ForwardRange forwardRange;
assert(forwardRange.size() == 8);
assert(static_cast<ForwardRange const&>(forwardRange).size() == 8);
@@ -284,12 +288,12 @@ constexpr bool testSize() {
return true;
}
-template<class T>
-concept SubscriptInvocable = requires (T const& obj, std::size_t n) { obj[n]; };
+template <class T>
+concept SubscriptInvocable = requires(T const& obj, std::size_t n) { obj[n]; };
constexpr bool testSubscript() {
static_assert(!SubscriptInvocable<ForwardRange>);
- static_assert( SubscriptInvocable<RARange>);
+ static_assert(SubscriptInvocable<RARange>);
RARange randomAccess;
assert(randomAccess[2] == 2);
@@ -300,17 +304,59 @@ constexpr bool testSubscript() {
return true;
}
-template<class T>
-concept FrontInvocable = requires (T const& obj) { obj.front(); };
+template <class T>
+concept AtInvocable = requires(T const& obj, std::size_t n) { obj.at(n); };
+
+#if TEST_STD_VER >= 29
+constexpr bool testAt() {
+ static_assert(!AtInvocable<ForwardRange>);
+ static_assert(AtInvocable<RARange>);
+
+ RARange randomAccess;
+ assert(randomAccess.at(2) == 2);
+ assert(static_cast<RARange const&>(randomAccess).at(2) == 2);
+ randomAccess.at(2) = 3;
+ assert(randomAccess.at(2) == 3);
+
+#ifndef TEST_HAS_NO_EXCEPTIONS
+ if (!std::is_constant_evaluated()) {
+ try {
+ TEST_IGNORE_NODISCARD randomAccess.at(0);
+ assert(true);
+ } catch (std::out_of_range const&) {
+ // pass
+ assert(false); // This should not be reached because index 0 is valid.
+ } catch (...) {
+ assert(false);
+ }
+
+ // Test that at() throws an exception when the index is out of range.
+ try {
+ TEST_IGNORE_NODISCARD randomAccess.at(10);
+ assert(false);
+ } catch (std::out_of_range const&) {
+ // pass
+ } catch (...) {
+ assert(false);
+ }
+ }
+#endif
+
+ return true;
+}
+#endif // TEST_STD_VER >= 29
+
+template <class T>
+concept FrontInvocable = requires(T const& obj) { obj.front(); };
-template<class T>
-concept BackInvocable = requires (T const& obj) { obj.back(); };
+template <class T>
+concept BackInvocable = requires(T const& obj) { obj.back(); };
constexpr bool testFrontBack() {
static_assert(!FrontInvocable<InputRange>);
- static_assert( FrontInvocable<ForwardRange>);
+ static_assert(FrontInvocable<ForwardRange>);
static_assert(!BackInvocable<ForwardRange>);
- static_assert( BackInvocable<RARange>);
+ static_assert(BackInvocable<RARange>);
ForwardRange forwardRange;
assert(forwardRange.front() == 0);
@@ -332,8 +378,10 @@ constexpr bool testFrontBack() {
return true;
}
-struct V1 : std::ranges::view_interface<V1> { };
-struct V2 : std::ranges::view_interface<V2> { V1 base_; };
+struct V1 : std::ranges::view_interface<V1> {};
+struct V2 : std::ranges::view_interface<V2> {
+ V1 base_;
+};
static_assert(sizeof(V2) == sizeof(V1));
int main(int, char**) {
@@ -349,6 +397,11 @@ int main(int, char**) {
testSubscript();
static_assert(testSubscript());
+#if TEST_STD_VER >= 29
+ testAt();
+ static_assert(testAt());
+#endif
+
testFrontBack();
static_assert(testFrontBack());
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index f4e16078d5af0..a2540256b3f1d 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1526,6 +1526,13 @@ def add_version_header(tc):
},
"headers": ["variant"],
},
+ {
+ "name": "__cpp_lib_view_interface",
+ "values": {
+ "c++20": 202606,
+ },
+ "headers": ["ranges"],
+ },
{
"name": "__cpp_lib_void_t",
"values": {"c++17": 201411},
>From 1f2ed195d0f1e5c763bedd8f0c04f47c609a7b27 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 17 Jul 2026 20:58:15 +0300
Subject: [PATCH 2/8] Fixes
---
libcxx/include/__ranges/view_interface.h | 6 +++---
.../range.utility/view.interface/view.interface.pass.cpp | 8 +++++---
2 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h
index c5875d024840e..c9f78966d1953 100644
--- a/libcxx/include/__ranges/view_interface.h
+++ b/libcxx/include/__ranges/view_interface.h
@@ -162,7 +162,7 @@ class view_interface {
return ranges::begin(__derived())[__index];
}
- #if _LIBCPP_STD_VER >= 29
+# if _LIBCPP_STD_VER >= 29
template <random_access_range _RARange = _Derived>
requires sized_range<_RARange> // freestanding-deleted
@@ -183,9 +183,9 @@ class view_interface {
}
return (*this)[__index];
}
-};
-#endif // _LIBCPP_STD_VER >= 29
+# endif // _LIBCPP_STD_VER >= 29
+};
} // namespace ranges
diff --git a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
index 047755b0dbb9e..ad871207c4c71 100644
--- a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
@@ -304,10 +304,11 @@ constexpr bool testSubscript() {
return true;
}
+#if TEST_STD_VER >= 29
+
template <class T>
concept AtInvocable = requires(T const& obj, std::size_t n) { obj.at(n); };
-#if TEST_STD_VER >= 29
constexpr bool testAt() {
static_assert(!AtInvocable<ForwardRange>);
static_assert(AtInvocable<RARange>);
@@ -318,7 +319,7 @@ constexpr bool testAt() {
randomAccess.at(2) = 3;
assert(randomAccess.at(2) == 3);
-#ifndef TEST_HAS_NO_EXCEPTIONS
+# ifndef TEST_HAS_NO_EXCEPTIONS
if (!std::is_constant_evaluated()) {
try {
TEST_IGNORE_NODISCARD randomAccess.at(0);
@@ -340,10 +341,11 @@ constexpr bool testAt() {
assert(false);
}
}
-#endif
+# endif
return true;
}
+
#endif // TEST_STD_VER >= 29
template <class T>
>From 8a866dcc7cae8300ff66255983f033f5364fe56c Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Fri, 17 Jul 2026 21:01:03 +0300
Subject: [PATCH 3/8] Docs
---
libcxx/docs/ReleaseNotes/24.rst | 1 +
libcxx/docs/Status/Cxx29Papers.csv | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/libcxx/docs/ReleaseNotes/24.rst b/libcxx/docs/ReleaseNotes/24.rst
index bcac37b8a717f..6773eb74007ee 100644
--- a/libcxx/docs/ReleaseNotes/24.rst
+++ b/libcxx/docs/ReleaseNotes/24.rst
@@ -38,6 +38,7 @@ What's New in Libc++ 24.0.0?
Implemented Papers
------------------
+- P3052R2: ``view_interface::at()`` (`Github <https://llvm.org/PR105185>`__)
Improvements and New Features
-----------------------------
diff --git a/libcxx/docs/Status/Cxx29Papers.csv b/libcxx/docs/Status/Cxx29Papers.csv
index 656eaf5df44df..55bbadd8a6342 100644
--- a/libcxx/docs/Status/Cxx29Papers.csv
+++ b/libcxx/docs/Status/Cxx29Papers.csv
@@ -4,7 +4,7 @@
"`P2414R12 <https://wg21.link/P2414R12>`__","Pointer lifetime-end zap proposed solutions","2026-06 (Brno)","","","`#204392 <https://github.com/llvm/llvm-project/issues/204392>`__","Voted as a Defect Report."
"`P3319R6 <https://wg21.link/P3319R6>`__","Add an ``iota`` object for ``simd`` (and more)","2026-06 (Brno)","","","`#204393 <https://github.com/llvm/llvm-project/issues/204393>`__",""
"`P3798R1 <https://wg21.link/P3798R1>`__","The unexpected in ``std::expected``","2026-06 (Brno)","","","`#204394 <https://github.com/llvm/llvm-project/issues/204394>`__",""
-"`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","|Complete|","23","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
+"`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","|Complete|","24","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","Applied as a Defect Report."
"`P3395R6 <https://wg21.link/P3395R6>`__","Fix encoding issues and add a formatter for ``std::error_code``","2026-06 (Brno)","","","`#204396 <https://github.com/llvm/llvm-project/issues/204396>`__",""
"`P3505R4 <https://wg21.link/P3505R4>`__","Fix the default floating-point representation in ``std::format``","2026-06 (Brno)","","","`#204397 <https://github.com/llvm/llvm-project/issues/204397>`__","To be applied as a Defect Report."
>From 88f74260da968566090e4082ed50311b9ec52885 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Aug 2026 16:11:53 +0300
Subject: [PATCH 4/8] Generator scripts
---
libcxx/docs/FeatureTestMacroTable.rst | 4 +-
libcxx/include/version | 2 +-
.../ranges.version.compile.pass.cpp | 158 ++++++++++++++++--
.../version.version.compile.pass.cpp | 40 +----
4 files changed, 147 insertions(+), 57 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index e5e33044e63c3..1306fbcde192c 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -555,7 +555,5 @@ Status
``__cpp_lib_variant`` ``202306L``
---------------------------------------------------------- -----------------
**C++29**
- ----------------------------------------------------------------------------
- ``__cpp_lib_view_interface`` *unimplemented*
- ========================================================== =================
+ ============================================================================
diff --git a/libcxx/include/version b/libcxx/include/version
index b0d63a7580904..a4a85e5497ed3 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -652,7 +652,7 @@ __cpp_lib_void_t 201411L <type_traits>
#endif
#if _LIBCPP_STD_VER >= 29
-// # define __cpp_lib_view_interface 202606L
+
#endif
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index 21abdf8f44a7c..a1c79df7e6c2c 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -84,10 +84,6 @@
# error "__cpp_lib_view_interface should not be defined before c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
#elif TEST_STD_VER == 14
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -154,10 +150,6 @@
# error "__cpp_lib_view_interface should not be defined before c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
#elif TEST_STD_VER == 17
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -224,10 +216,6 @@
# error "__cpp_lib_view_interface should not be defined before c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
#elif TEST_STD_VER == 20
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -300,10 +288,6 @@
# error "__cpp_lib_view_interface should have the value 202606L in c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
#elif TEST_STD_VER == 23
# ifdef __cpp_lib_default_template_type_for_algorithm_values
@@ -427,7 +411,7 @@
# error "__cpp_lib_view_interface should have the value 202606L in c++23"
# endif
-#elif TEST_STD_VER > 23
+#elif TEST_STD_VER == 26
# if !defined(_LIBCPP_VERSION)
# ifndef __cpp_lib_default_template_type_for_algorithm_values
@@ -565,6 +549,144 @@
# error "__cpp_lib_view_interface should have the value 202606L in c++26"
# endif
-#endif // TEST_STD_VER > 23
+#elif TEST_STD_VER > 26
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_default_template_type_for_algorithm_values
+# error "__cpp_lib_default_template_type_for_algorithm_values should be defined in c++29"
+# endif
+# if __cpp_lib_default_template_type_for_algorithm_values != 202403L
+# error "__cpp_lib_default_template_type_for_algorithm_values should have the value 202403L in c++29"
+# endif
+# else
+# ifdef __cpp_lib_default_template_type_for_algorithm_values
+# error "__cpp_lib_default_template_type_for_algorithm_values should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+# ifndef __cpp_lib_ranges
+# error "__cpp_lib_ranges should be defined in c++29"
+# endif
+# if __cpp_lib_ranges != 202406L
+# error "__cpp_lib_ranges should have the value 202406L in c++29"
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_ranges_as_const
+# error "__cpp_lib_ranges_as_const should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_as_const != 202207L
+# error "__cpp_lib_ranges_as_const should have the value 202207L in c++29"
+# endif
+# else
+# ifdef __cpp_lib_ranges_as_const
+# error "__cpp_lib_ranges_as_const should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+# ifndef __cpp_lib_ranges_as_rvalue
+# error "__cpp_lib_ranges_as_rvalue should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_as_rvalue != 202207L
+# error "__cpp_lib_ranges_as_rvalue should have the value 202207L in c++29"
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_ranges_chunk
+# error "__cpp_lib_ranges_chunk should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_chunk != 202202L
+# error "__cpp_lib_ranges_chunk should have the value 202202L in c++29"
+# endif
+# else
+# ifdef __cpp_lib_ranges_chunk
+# error "__cpp_lib_ranges_chunk should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+# ifndef __cpp_lib_ranges_chunk_by
+# error "__cpp_lib_ranges_chunk_by should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_chunk_by != 202202L
+# error "__cpp_lib_ranges_chunk_by should have the value 202202L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_concat
+# error "__cpp_lib_ranges_concat should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_concat != 202403L
+# error "__cpp_lib_ranges_concat should have the value 202403L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_enumerate
+# error "__cpp_lib_ranges_enumerate should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_enumerate != 202302L
+# error "__cpp_lib_ranges_enumerate should have the value 202302L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_indices
+# error "__cpp_lib_ranges_indices should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_indices != 202506L
+# error "__cpp_lib_ranges_indices should have the value 202506L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_join_with
+# error "__cpp_lib_ranges_join_with should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_join_with != 202202L
+# error "__cpp_lib_ranges_join_with should have the value 202202L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_repeat
+# error "__cpp_lib_ranges_repeat should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_repeat != 202207L
+# error "__cpp_lib_ranges_repeat should have the value 202207L in c++29"
+# endif
+
+# if !defined(_LIBCPP_VERSION)
+# ifndef __cpp_lib_ranges_slide
+# error "__cpp_lib_ranges_slide should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_slide != 202202L
+# error "__cpp_lib_ranges_slide should have the value 202202L in c++29"
+# endif
+# else
+# ifdef __cpp_lib_ranges_slide
+# error "__cpp_lib_ranges_slide should not be defined because it is unimplemented in libc++!"
+# endif
+# endif
+
+# ifndef __cpp_lib_ranges_stride
+# error "__cpp_lib_ranges_stride should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_stride != 202207L
+# error "__cpp_lib_ranges_stride should have the value 202207L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_to_container
+# error "__cpp_lib_ranges_to_container should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_to_container != 202202L
+# error "__cpp_lib_ranges_to_container should have the value 202202L in c++29"
+# endif
+
+# ifndef __cpp_lib_ranges_zip
+# error "__cpp_lib_ranges_zip should be defined in c++29"
+# endif
+# if __cpp_lib_ranges_zip != 202110L
+# error "__cpp_lib_ranges_zip should have the value 202110L in c++29"
+# endif
+
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++29"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++29"
+# endif
+
+#endif // TEST_STD_VER > 26
// clang-format on
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 b9eb4c962be0b..2c61c9f27661e 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
@@ -960,10 +960,6 @@
# error "__cpp_lib_view_interface should not be defined before c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
# ifdef __cpp_lib_void_t
# error "__cpp_lib_void_t should not be defined before c++17"
# endif
@@ -1988,10 +1984,6 @@
# error "__cpp_lib_view_interface should not be defined before c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
# ifdef __cpp_lib_void_t
# error "__cpp_lib_void_t should not be defined before c++17"
# endif
@@ -3205,10 +3197,6 @@
# error "__cpp_lib_view_interface should not be defined before c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++17"
# endif
@@ -4692,10 +4680,6 @@
# error "__cpp_lib_view_interface should have the value 202606L in c++20"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++20"
# endif
@@ -6407,10 +6391,6 @@
# error "__cpp_lib_view_interface should have the value 202606L in c++23"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++23"
# endif
@@ -8437,10 +8417,6 @@
# error "__cpp_lib_view_interface should have the value 202606L in c++26"
# endif
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++29"
-# endif
-
# ifndef __cpp_lib_void_t
# error "__cpp_lib_void_t should be defined in c++26"
# endif
@@ -10460,17 +10436,11 @@
# error "__cpp_lib_variant should have the value 202306L in c++29"
# endif
-# if !defined(_LIBCPP_VERSION)
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++29"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++29"
-# endif
-# else
-# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined because it is unimplemented in libc++!"
-# endif
+# ifndef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should be defined in c++29"
+# endif
+# if __cpp_lib_view_interface != 202606L
+# error "__cpp_lib_view_interface should have the value 202606L in c++29"
# endif
# ifndef __cpp_lib_void_t
>From 9423e10ef9dadce165f5945d12bc9b61c91a3ab8 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Aug 2026 16:14:15 +0300
Subject: [PATCH 5/8] Fixes
---
libcxx/docs/FeatureTestMacroTable.rst | 6 ++---
libcxx/include/version | 3 +--
.../ranges.version.compile.pass.cpp | 27 +++++++------------
.../version.version.compile.pass.cpp | 27 +++++++------------
.../generate_feature_test_macro_components.py | 2 +-
5 files changed, 23 insertions(+), 42 deletions(-)
diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 1306fbcde192c..9c762989feeef 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -312,8 +312,6 @@ Status
---------------------------------------------------------- -----------------
``__cpp_lib_variant`` ``202106L``
---------------------------------------------------------- -----------------
- ``__cpp_lib_view_interface`` ``202606L``
- ---------------------------------------------------------- -----------------
**C++23**
----------------------------------------------------------------------------
``__cpp_lib_adaptor_iterator_pair_constructor`` ``202106L``
@@ -555,5 +553,7 @@ Status
``__cpp_lib_variant`` ``202306L``
---------------------------------------------------------- -----------------
**C++29**
- ============================================================================
+ ----------------------------------------------------------------------------
+ ``__cpp_lib_view_interface`` ``202606L``
+ ========================================================== =================
diff --git a/libcxx/include/version b/libcxx/include/version
index a4a85e5497ed3..a58a436bbf275 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -493,7 +493,6 @@ __cpp_lib_void_t 201411L <type_traits>
# define __cpp_lib_unwrap_ref 201811L
# undef __cpp_lib_variant
# define __cpp_lib_variant 202106L
-# define __cpp_lib_view_interface 202606L
#endif
#if _LIBCPP_STD_VER >= 23
@@ -652,7 +651,7 @@ __cpp_lib_void_t 201411L <type_traits>
#endif
#if _LIBCPP_STD_VER >= 29
-
+# define __cpp_lib_view_interface 202606L
#endif
#endif // __cplusplus < 201103L && defined(_LIBCPP_USE_FROZEN_CXX03_HEADERS)
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
index a1c79df7e6c2c..1b507cdafb33a 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/ranges.version.compile.pass.cpp
@@ -81,7 +81,7 @@
# endif
# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++20"
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
#elif TEST_STD_VER == 14
@@ -147,7 +147,7 @@
# endif
# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++20"
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
#elif TEST_STD_VER == 17
@@ -213,7 +213,7 @@
# endif
# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++20"
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
#elif TEST_STD_VER == 20
@@ -281,11 +281,8 @@
# error "__cpp_lib_ranges_zip should not be defined before c++23"
# endif
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++20"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++20"
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
#elif TEST_STD_VER == 23
@@ -404,11 +401,8 @@
# error "__cpp_lib_ranges_zip should have the value 202110L in c++23"
# endif
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++23"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++23"
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
#elif TEST_STD_VER == 26
@@ -542,11 +536,8 @@
# error "__cpp_lib_ranges_zip should have the value 202110L in c++26"
# endif
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++26"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++26"
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
#elif TEST_STD_VER > 26
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 2c61c9f27661e..fc373b44cd500 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
@@ -957,7 +957,7 @@
# endif
# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++20"
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
# ifdef __cpp_lib_void_t
@@ -1981,7 +1981,7 @@
# endif
# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++20"
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
# ifdef __cpp_lib_void_t
@@ -3194,7 +3194,7 @@
# endif
# ifdef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should not be defined before c++20"
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
# ifndef __cpp_lib_void_t
@@ -4673,11 +4673,8 @@
# error "__cpp_lib_variant should have the value 202106L in c++20"
# endif
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++20"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++20"
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
# ifndef __cpp_lib_void_t
@@ -6384,11 +6381,8 @@
# error "__cpp_lib_variant should have the value 202106L in c++23"
# endif
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++23"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++23"
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
# ifndef __cpp_lib_void_t
@@ -8410,11 +8404,8 @@
# error "__cpp_lib_variant should have the value 202306L in c++26"
# endif
-# ifndef __cpp_lib_view_interface
-# error "__cpp_lib_view_interface should be defined in c++26"
-# endif
-# if __cpp_lib_view_interface != 202606L
-# error "__cpp_lib_view_interface should have the value 202606L in c++26"
+# ifdef __cpp_lib_view_interface
+# error "__cpp_lib_view_interface should not be defined before c++29"
# endif
# ifndef __cpp_lib_void_t
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index 9ee19577ddb39..e3683f4a78ba7 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -1536,7 +1536,7 @@ def add_version_header(tc):
{
"name": "__cpp_lib_view_interface",
"values": {
- "c++20": 202606,
+ "c++29": 202606, # P3052R2 view_interface::at()
},
"headers": ["ranges"],
},
>From 7faa21bc428aab9ad2fa5ea52ce33e30e902764e Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Aug 2026 19:57:19 +0300
Subject: [PATCH 6/8] Fix
---
libcxx/test/libcxx/transitive_includes/cxx23.csv | 1 -
libcxx/test/libcxx/transitive_includes/cxx26.csv | 1 -
2 files changed, 2 deletions(-)
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index 8c03f1c3c2251..a199c610e9f57 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -11,7 +11,6 @@ algorithm iosfwd
algorithm limits
algorithm optional
algorithm ratio
-algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index 3f4daee66625a..bd9227ca685d0 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -10,7 +10,6 @@ algorithm initializer_list
algorithm iosfwd
algorithm limits
algorithm ratio
-algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
>From 0ac3ef61e6b4f46c1cf6bee97f689ee275d44e53 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Aug 2026 20:48:01 +0300
Subject: [PATCH 7/8] Fix `nodiscard`
---
.../ranges/range.utility/view.interface/nodiscard.verify.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
index 2bccc170aa727..3d4c365ddfe6e 100644
--- a/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
+++ b/libcxx/test/libcxx/ranges/range.utility/view.interface/nodiscard.verify.cpp
@@ -13,6 +13,8 @@
#include <ranges>
#include <utility>
+#include "test_macros.h"
+
struct View : std::ranges::view_interface<View> {
int* begin();
int* end();
>From 4531b858f77257046cf5837929b9812c4b97fa45 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Thu, 27 Aug 2026 20:56:12 +0300
Subject: [PATCH 8/8] transitive includes
---
libcxx/test/libcxx/transitive_includes/cxx20.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx23.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx26.csv | 1 +
libcxx/test/libcxx/transitive_includes/cxx29.csv | 1 +
4 files changed, 4 insertions(+)
diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 44b5fe1f1577f..3c5e9439f100c 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -11,6 +11,7 @@ algorithm iosfwd
algorithm limits
algorithm optional
algorithm ratio
+algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv
index a199c610e9f57..8c03f1c3c2251 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -11,6 +11,7 @@ algorithm iosfwd
algorithm limits
algorithm optional
algorithm ratio
+algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv
index bd9227ca685d0..3f4daee66625a 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -10,6 +10,7 @@ algorithm initializer_list
algorithm iosfwd
algorithm limits
algorithm ratio
+algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
diff --git a/libcxx/test/libcxx/transitive_includes/cxx29.csv b/libcxx/test/libcxx/transitive_includes/cxx29.csv
index bd9227ca685d0..3f4daee66625a 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx29.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx29.csv
@@ -10,6 +10,7 @@ algorithm initializer_list
algorithm iosfwd
algorithm limits
algorithm ratio
+algorithm stdexcept
algorithm tuple
algorithm version
any cstdint
More information about the libcxx-commits
mailing list