Skip to content

Commit 026210e

Browse files
[libc++][ranges] P2609R3: Relaxing Ranges Just A Smidge (#101715)
This patch implements https://wg21.link/p2609r3. The test code was originally authored by JMazurkiewicz. Notes: - P2609R3 is not officially a Defect Report, but MSVC STL implements it in C++20 mode. Moreover, P2609R3 and P2997R1 touch exactly the same set of concepts, and MSVC STL and libc++ have already treated P2997R1 as a DR. - This patch also adjusted feature-test macros. + In C++20 mode, the value of __cpp_lib_ranges should be `202110L` because - `202202L` covers `range_adaptor_closure` (P2387R3), and - `202207L` covers move-only types in range adaptors (P2494R2). And all of these changes are only available since C++23 mode. + In C++23 mode, the value should be `202406L` because - `202211L` covers removing poison overloads (P2602R2), - `202302L` covers relaxing projected value types (P2609R3), and - `202406L` covers removing requirements on `iter_common_reference_t` (P2997R1). And all of these changes are already or being implemented. Fixes #105253. Co-authored-by: Jakub Mazurkiewicz <[email protected]>
1 parent 71ede8d commit 026210e

15 files changed

+199
-64
lines changed

libcxx/docs/FeatureTestMacroTable.rst

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ Status
266266
---------------------------------------------------------- -----------------
267267
``__cpp_lib_polymorphic_allocator`` ``201902L``
268268
---------------------------------------------------------- -----------------
269-
``__cpp_lib_ranges`` ``202207L``
269+
``__cpp_lib_ranges`` ``202110L``
270270
---------------------------------------------------------- -----------------
271271
``__cpp_lib_remove_cvref`` ``201711L``
272272
---------------------------------------------------------- -----------------
@@ -350,6 +350,8 @@ Status
350350
---------------------------------------------------------- -----------------
351351
``__cpp_lib_print`` ``202207L``
352352
---------------------------------------------------------- -----------------
353+
``__cpp_lib_ranges`` ``202406L``
354+
---------------------------------------------------------- -----------------
353355
``__cpp_lib_ranges_as_const`` *unimplemented*
354356
---------------------------------------------------------- -----------------
355357
``__cpp_lib_ranges_as_rvalue`` ``202207L``

libcxx/docs/ReleaseNotes/20.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ What's New in Libc++ 20.0.0?
3838
Implemented Papers
3939
------------------
4040

41+
- P2609R3: Relaxing Ranges Just A Smidge (`Github <https://github.com/llvm/llvm-project/issues/105253>`__)
4142
- P2985R0: A type trait for detecting virtual base classes (`Github <https://github.com/llvm/llvm-project/issues/105432>`__)
4243

4344

libcxx/docs/Status/Cxx23.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Paper Status
4444
.. [#note-P2520R0] P2520R0: Libc++ implemented this paper as a DR in C++20 as well.
4545
.. [#note-P2711R1] P2711R1: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
4646
.. [#note-P2770R0] P2770R0: ``join_with_view`` hasn't been done yet since this type isn't implemented yet.
47+
.. [#note-P2609R3] P2609R3: Libc++ implemented this paper as a DR in C++20 as well. (MSVC STL does the same.)
4748
.. [#note-LWG3494] LWG3494: That LWG issue was superseded by `P2017R1 <https://wg21.link/P2017R1>`__.
4849
.. [#note-LWG3481] LWG3481: That LWG issue was superseded by `P2415R2 <https://wg21.link/P2415R2>`__.
4950
.. [#note-LWG3265] LWG3265: That LWG issue was resolved by `LWG3435 <https://wg21.link/LWG3435>`__.

libcxx/docs/Status/Cxx23Papers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@
107107
"`P2770R0 <https://wg21.link/P2770R0>`__","Stashing stashing ``iterators`` for proper flattening","2023-02 (Issaquah)","|Partial| [#note-P2770R0]_","","|ranges|"
108108
"`P2164R9 <https://wg21.link/P2164R9>`__","``views::enumerate``","2023-02 (Issaquah)","","","|ranges|"
109109
"`P2711R1 <https://wg21.link/P2711R1>`__","Making multi-param constructors of ``views`` ``explicit``","2023-02 (Issaquah)","|In Progress| [#note-P2711R1]_","","|ranges|"
110-
"`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","","","|ranges|"
110+
"`P2609R3 <https://wg21.link/P2609R3>`__","Relaxing Ranges Just A Smidge","2023-02 (Issaquah)","|Complete| [#note-P2609R3]_","20.0","|ranges|"
111111
"`P2713R1 <https://wg21.link/P2713R1>`__","Escaping improvements in ``std::format``","2023-02 (Issaquah)","|Complete|","19.0","|format|"
112112
"`P2675R1 <https://wg21.link/P2675R1>`__","``format``'s width estimation is too approximate and not forward compatible","2023-02 (Issaquah)","|Complete|","17.0","|format|"
113113
"`P2572R1 <https://wg21.link/P2572R1>`__","``std::format`` fill character allowances","2023-02 (Issaquah)","|Complete|","17.0","|format|"

libcxx/include/__iterator/concepts.h

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include <__type_traits/add_pointer.h>
3636
#include <__type_traits/common_reference.h>
3737
#include <__type_traits/is_pointer.h>
38+
#include <__type_traits/is_primary_template.h>
3839
#include <__type_traits/is_reference.h>
3940
#include <__type_traits/remove_cv.h>
4041
#include <__type_traits/remove_cvref.h>
@@ -64,8 +65,33 @@ concept __indirectly_readable_impl =
6465
template <class _In>
6566
concept indirectly_readable = __indirectly_readable_impl<remove_cvref_t<_In>>;
6667

68+
template <class _Tp>
69+
using __projected_iterator_t = typename _Tp::__projected_iterator;
70+
71+
template <class _Tp>
72+
using __projected_projection_t = typename _Tp::__projected_projection;
73+
74+
template <class _Tp>
75+
concept __specialization_of_projected = requires {
76+
typename __projected_iterator_t<_Tp>;
77+
typename __projected_projection_t<_Tp>;
78+
} && __is_primary_template<_Tp>::value;
79+
80+
template <class _Tp>
81+
struct __indirect_value_t_impl {
82+
using type = iter_value_t<_Tp>&;
83+
};
84+
template <__specialization_of_projected _Tp>
85+
struct __indirect_value_t_impl<_Tp> {
86+
using type = invoke_result_t<__projected_projection_t<_Tp>&,
87+
typename __indirect_value_t_impl<__projected_iterator_t<_Tp>>::type>;
88+
};
89+
90+
template <indirectly_readable _Tp>
91+
using __indirect_value_t = typename __indirect_value_t_impl<_Tp>::type;
92+
6793
template <indirectly_readable _Tp>
68-
using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
94+
using iter_common_reference_t = common_reference_t<iter_reference_t<_Tp>, __indirect_value_t<_Tp>>;
6995

7096
// [iterator.concept.writable]
7197
template <class _Out, class _Tp>
@@ -176,43 +202,45 @@ concept __has_arrow = input_iterator<_Ip> && (is_pointer_v<_Ip> || requires(_Ip
176202
// [indirectcallable.indirectinvocable]
177203
template <class _Fp, class _It>
178204
concept indirectly_unary_invocable =
179-
indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, iter_value_t<_It>&> &&
205+
indirectly_readable<_It> && copy_constructible<_Fp> && invocable<_Fp&, __indirect_value_t<_It>> &&
180206
invocable<_Fp&, iter_reference_t<_It>> &&
181-
common_reference_with< invoke_result_t<_Fp&, iter_value_t<_It>&>, invoke_result_t<_Fp&, iter_reference_t<_It>>>;
207+
common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
208+
invoke_result_t<_Fp&, iter_reference_t<_It>>>;
182209

183210
template <class _Fp, class _It>
184211
concept indirectly_regular_unary_invocable =
185-
indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, iter_value_t<_It>&> &&
212+
indirectly_readable<_It> && copy_constructible<_Fp> && regular_invocable<_Fp&, __indirect_value_t<_It>> &&
186213
regular_invocable<_Fp&, iter_reference_t<_It>> &&
187-
common_reference_with< invoke_result_t<_Fp&, iter_value_t<_It>&>, invoke_result_t<_Fp&, iter_reference_t<_It>>>;
214+
common_reference_with< invoke_result_t<_Fp&, __indirect_value_t<_It>>,
215+
invoke_result_t<_Fp&, iter_reference_t<_It>>>;
188216

189217
template <class _Fp, class _It>
190218
concept indirect_unary_predicate =
191-
indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, iter_value_t<_It>&> &&
219+
indirectly_readable<_It> && copy_constructible<_Fp> && predicate<_Fp&, __indirect_value_t<_It>> &&
192220
predicate<_Fp&, iter_reference_t<_It>>;
193221

194222
template <class _Fp, class _It1, class _It2>
195223
concept indirect_binary_predicate =
196224
indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
197-
predicate<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
198-
predicate<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
199-
predicate<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
225+
predicate<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
226+
predicate<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
227+
predicate<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
200228
predicate<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
201229

202230
template <class _Fp, class _It1, class _It2 = _It1>
203231
concept indirect_equivalence_relation =
204232
indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
205-
equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
206-
equivalence_relation<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
207-
equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
233+
equivalence_relation<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
234+
equivalence_relation<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
235+
equivalence_relation<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
208236
equivalence_relation<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
209237

210238
template <class _Fp, class _It1, class _It2 = _It1>
211239
concept indirect_strict_weak_order =
212240
indirectly_readable<_It1> && indirectly_readable<_It2> && copy_constructible<_Fp> &&
213-
strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_value_t<_It2>&> &&
214-
strict_weak_order<_Fp&, iter_value_t<_It1>&, iter_reference_t<_It2>> &&
215-
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_value_t<_It2>&> &&
241+
strict_weak_order<_Fp&, __indirect_value_t<_It1>, __indirect_value_t<_It2>> &&
242+
strict_weak_order<_Fp&, __indirect_value_t<_It1>, iter_reference_t<_It2>> &&
243+
strict_weak_order<_Fp&, iter_reference_t<_It1>, __indirect_value_t<_It2>> &&
216244
strict_weak_order<_Fp&, iter_reference_t<_It1>, iter_reference_t<_It2>>;
217245

218246
template <class _Fp, class... _Its>

libcxx/include/__iterator/projected.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ _LIBCPP_BEGIN_NAMESPACE_STD
2626
template <class _It, class _Proj>
2727
struct __projected_impl {
2828
struct __type {
29+
using __primary_template = __type;
30+
using __projected_iterator = _It;
31+
using __projected_projection = _Proj;
32+
2933
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
3034
indirect_result_t<_Proj&, _It> operator*() const; // not defined
3135
};
@@ -34,6 +38,10 @@ struct __projected_impl {
3438
template <weakly_incrementable _It, class _Proj>
3539
struct __projected_impl<_It, _Proj> {
3640
struct __type {
41+
using __primary_template = __type;
42+
using __projected_iterator = _It;
43+
using __projected_projection = _Proj;
44+
3745
using value_type = remove_cvref_t<indirect_result_t<_Proj&, _It>>;
3846
using difference_type = iter_difference_t<_It>;
3947
indirect_result_t<_Proj&, _It> operator*() const; // not defined

libcxx/include/version

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,9 @@ __cpp_lib_philox_engine 202406L <random>
182182
__cpp_lib_polymorphic_allocator 201902L <memory_resource>
183183
__cpp_lib_print 202207L <ostream> <print>
184184
__cpp_lib_quoted_string_io 201304L <iomanip>
185-
__cpp_lib_ranges 202207L <algorithm> <functional> <iterator>
185+
__cpp_lib_ranges 202406L <algorithm> <functional> <iterator>
186186
<memory> <ranges>
187+
202110L // C++20
187188
__cpp_lib_ranges_as_const 202207L <ranges>
188189
__cpp_lib_ranges_as_rvalue 202207L <ranges>
189190
__cpp_lib_ranges_chunk 202202L <ranges>
@@ -428,7 +429,7 @@ __cpp_lib_void_t 201411L <type_traits>
428429
# if _LIBCPP_AVAILABILITY_HAS_PMR
429430
# define __cpp_lib_polymorphic_allocator 201902L
430431
# endif
431-
# define __cpp_lib_ranges 202207L
432+
# define __cpp_lib_ranges 202110L
432433
# define __cpp_lib_remove_cvref 201711L
433434
# if !defined(_LIBCPP_HAS_NO_THREADS) && _LIBCPP_AVAILABILITY_HAS_SYNC
434435
# define __cpp_lib_semaphore 201907L
@@ -480,6 +481,8 @@ __cpp_lib_void_t 201411L <type_traits>
480481
# define __cpp_lib_optional 202110L
481482
# define __cpp_lib_out_ptr 202106L
482483
# define __cpp_lib_print 202207L
484+
# undef __cpp_lib_ranges
485+
# define __cpp_lib_ranges 202406L
483486
// # define __cpp_lib_ranges_as_const 202207L
484487
# define __cpp_lib_ranges_as_rvalue 202207L
485488
// # define __cpp_lib_ranges_chunk 202202L
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// template<indirectly_readable T>
12+
// using indirect-value-t = see below; // exposition only
13+
14+
#include <cassert>
15+
16+
#include <algorithm>
17+
#include <memory>
18+
#include <ranges>
19+
#include <utility>
20+
#include <vector>
21+
22+
#include "test_macros.h"
23+
24+
TEST_CONSTEXPR_CXX23 void test() {
25+
auto ints = std::views::iota(0, 5);
26+
auto unique_ptr_maker = []<std::movable T>(T v) { return std::make_unique<T>(std::move(v)); };
27+
28+
using iota_iter = std::ranges::iterator_t<decltype(ints)>;
29+
using unique_ptr_projection = decltype(unique_ptr_maker);
30+
using projected_iter = std::projected<iota_iter, unique_ptr_projection>;
31+
32+
{ // Check std::indirectly_unary_invocable
33+
auto consume = [](auto) {};
34+
static_assert(std::indirectly_unary_invocable<decltype(consume), projected_iter>);
35+
36+
std::ranges::for_each(ints, consume, unique_ptr_maker);
37+
std::ranges::for_each(ints.begin(), ints.end(), consume, unique_ptr_maker);
38+
}
39+
40+
{ // Check std::indirectly_regular_unary_invocable
41+
static_assert(std::indirectly_regular_unary_invocable<decltype([](auto) {}), projected_iter>);
42+
using check_wellformedness [[maybe_unused]] = std::projected<projected_iter, unique_ptr_projection>;
43+
}
44+
45+
{ // Check std::indirect_unary_predicate
46+
auto unary_pred = [](auto) { return false; };
47+
static_assert(std::indirect_unary_predicate<decltype(unary_pred), projected_iter>);
48+
49+
assert(std::ranges::find_if(ints, unary_pred, unique_ptr_maker) == ints.end());
50+
assert(std::ranges::find_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker) == ints.end());
51+
assert(std::ranges::count_if(ints, unary_pred, unique_ptr_maker) == 0);
52+
assert(std::ranges::count_if(ints.begin(), ints.end(), unary_pred, unique_ptr_maker) == 0);
53+
}
54+
55+
{ // Check std::indirect_binary_predicate
56+
auto binary_pred = [](auto, auto) { return false; };
57+
static_assert(std::indirect_binary_predicate<decltype(binary_pred), projected_iter, projected_iter>);
58+
59+
assert(std::ranges::adjacent_find(ints, binary_pred, unique_ptr_maker) == ints.end());
60+
assert(std::ranges::adjacent_find(ints.begin(), ints.end(), binary_pred, unique_ptr_maker) == ints.end());
61+
}
62+
63+
{ // Check std::indirect_equivalence_relation
64+
auto rel = [](auto, auto) { return false; };
65+
static_assert(std::indirect_equivalence_relation<decltype(rel), projected_iter>);
66+
67+
std::vector<int> out;
68+
(void)std::ranges::unique_copy(ints, std::back_inserter(out), rel, unique_ptr_maker);
69+
(void)std::ranges::unique_copy(ints.begin(), ints.end(), std::back_inserter(out), rel, unique_ptr_maker);
70+
}
71+
72+
{ // Check std::indirect_strict_weak_order
73+
auto rel = [](auto x, auto y) { return *x < *y; };
74+
static_assert(std::indirect_strict_weak_order<decltype(rel), projected_iter>);
75+
76+
assert(std::ranges::is_sorted_until(ints, rel, unique_ptr_maker) == ints.end());
77+
assert(std::ranges::is_sorted_until(ints.begin(), ints.end(), rel, unique_ptr_maker) == ints.end());
78+
}
79+
}
80+
81+
int main(int, char**) {
82+
test();
83+
#if TEST_STD_VER >= 23
84+
static_assert((test(), true));
85+
#endif
86+
return 0;
87+
}

libcxx/test/std/language.support/support.limits/support.limits.general/algorithm.version.compile.pass.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
__cpp_lib_default_template_type_for_algorithm_values 202403L [C++26]
2222
__cpp_lib_freestanding_algorithm 202311L [C++26]
2323
__cpp_lib_parallel_algorithm 201603L [C++17]
24-
__cpp_lib_ranges 202207L [C++20]
24+
__cpp_lib_ranges 202110L [C++20]
25+
202406L [C++23]
2526
__cpp_lib_ranges_contains 202207L [C++23]
2627
__cpp_lib_ranges_find_last 202207L [C++23]
2728
__cpp_lib_ranges_starts_ends_with 202106L [C++23]
@@ -244,8 +245,8 @@
244245
# ifndef __cpp_lib_ranges
245246
# error "__cpp_lib_ranges should be defined in c++20"
246247
# endif
247-
# if __cpp_lib_ranges != 202207L
248-
# error "__cpp_lib_ranges should have the value 202207L in c++20"
248+
# if __cpp_lib_ranges != 202110L
249+
# error "__cpp_lib_ranges should have the value 202110L in c++20"
249250
# endif
250251

251252
# ifdef __cpp_lib_ranges_contains
@@ -321,8 +322,8 @@
321322
# ifndef __cpp_lib_ranges
322323
# error "__cpp_lib_ranges should be defined in c++23"
323324
# endif
324-
# if __cpp_lib_ranges != 202207L
325-
# error "__cpp_lib_ranges should have the value 202207L in c++23"
325+
# if __cpp_lib_ranges != 202406L
326+
# error "__cpp_lib_ranges should have the value 202406L in c++23"
326327
# endif
327328

328329
# ifndef __cpp_lib_ranges_contains
@@ -425,8 +426,8 @@
425426
# ifndef __cpp_lib_ranges
426427
# error "__cpp_lib_ranges should be defined in c++26"
427428
# endif
428-
# if __cpp_lib_ranges != 202207L
429-
# error "__cpp_lib_ranges should have the value 202207L in c++26"
429+
# if __cpp_lib_ranges != 202406L
430+
# error "__cpp_lib_ranges should have the value 202406L in c++26"
430431
# endif
431432

432433
# ifndef __cpp_lib_ranges_contains

libcxx/test/std/language.support/support.limits/support.limits.general/functional.version.compile.pass.cpp

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
__cpp_lib_invoke_r 202106L [C++23]
2828
__cpp_lib_move_only_function 202110L [C++23]
2929
__cpp_lib_not_fn 201603L [C++17]
30-
__cpp_lib_ranges 202207L [C++20]
30+
__cpp_lib_ranges 202110L [C++20]
31+
202406L [C++23]
3132
__cpp_lib_reference_wrapper 202403L [C++26]
3233
__cpp_lib_result_of_sfinae 201210L [C++14]
3334
__cpp_lib_transparent_operators 201210L [C++14]
@@ -305,8 +306,8 @@
305306
# ifndef __cpp_lib_ranges
306307
# error "__cpp_lib_ranges should be defined in c++20"
307308
# endif
308-
# if __cpp_lib_ranges != 202207L
309-
# error "__cpp_lib_ranges should have the value 202207L in c++20"
309+
# if __cpp_lib_ranges != 202110L
310+
# error "__cpp_lib_ranges should have the value 202110L in c++20"
310311
# endif
311312

312313
# ifdef __cpp_lib_reference_wrapper
@@ -409,8 +410,8 @@
409410
# ifndef __cpp_lib_ranges
410411
# error "__cpp_lib_ranges should be defined in c++23"
411412
# endif
412-
# if __cpp_lib_ranges != 202207L
413-
# error "__cpp_lib_ranges should have the value 202207L in c++23"
413+
# if __cpp_lib_ranges != 202406L
414+
# error "__cpp_lib_ranges should have the value 202406L in c++23"
414415
# endif
415416

416417
# ifdef __cpp_lib_reference_wrapper
@@ -531,8 +532,8 @@
531532
# ifndef __cpp_lib_ranges
532533
# error "__cpp_lib_ranges should be defined in c++26"
533534
# endif
534-
# if __cpp_lib_ranges != 202207L
535-
# error "__cpp_lib_ranges should have the value 202207L in c++26"
535+
# if __cpp_lib_ranges != 202406L
536+
# error "__cpp_lib_ranges should have the value 202406L in c++26"
536537
# endif
537538

538539
# ifndef __cpp_lib_reference_wrapper

0 commit comments

Comments
 (0)