Skip to content

Commit 8be6797

Browse files
[libc++][ranges] Ensure range access CPOs are provided in <iterator>
Per [range.access.general]/1, these CPOs are also provided in `<iterator>`. Currently only some of them are provided via transitive inclusion when only `<iterator>` is included. Drive-by: Add an entry for `ranges::reserve_hint` in the general test file for CPOs.
1 parent 149d4b5 commit 8be6797

File tree

4 files changed

+75
-7
lines changed

4 files changed

+75
-7
lines changed

libcxx/include/iterator

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,16 @@ template <class E> constexpr const E* data(initializer_list<E> il) noexcept;
737737
# include <compare>
738738
# include <concepts>
739739

740+
// [range.access.general]
741+
# if _LIBCPP_STD_VER >= 20
742+
# include <__ranges/access.h>
743+
# include <__ranges/data.h>
744+
# include <__ranges/empty.h>
745+
# include <__ranges/rbegin.h>
746+
# include <__ranges/rend.h>
747+
# include <__ranges/size.h>
748+
# endif
749+
740750
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
741751
# pragma GCC system_header
742752
# endif

libcxx/include/ranges

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -405,30 +405,24 @@ namespace std {
405405
# include <__config>
406406

407407
# if _LIBCPP_STD_VER >= 20
408-
# include <__ranges/access.h>
409408
# include <__ranges/all.h>
410409
# include <__ranges/common_view.h>
411410
# include <__ranges/concepts.h>
412411
# include <__ranges/counted.h>
413412
# include <__ranges/dangling.h>
414-
# include <__ranges/data.h>
415413
# include <__ranges/drop_view.h>
416414
# include <__ranges/drop_while_view.h>
417415
# include <__ranges/elements_view.h>
418-
# include <__ranges/empty.h>
419416
# include <__ranges/empty_view.h>
420417
# include <__ranges/enable_borrowed_range.h>
421418
# include <__ranges/enable_view.h>
422419
# include <__ranges/filter_view.h>
423420
# include <__ranges/iota_view.h>
424421
# include <__ranges/join_view.h>
425422
# include <__ranges/lazy_split_view.h>
426-
# include <__ranges/rbegin.h>
427423
# include <__ranges/ref_view.h>
428-
# include <__ranges/rend.h>
429424
# include <__ranges/reverse_view.h>
430425
# include <__ranges/single_view.h>
431-
# include <__ranges/size.h>
432426
# include <__ranges/split_view.h>
433427
# include <__ranges/subrange.h>
434428
# include <__ranges/take_view.h>
@@ -460,7 +454,7 @@ namespace std {
460454
// [ranges.syn]
461455
# include <compare>
462456
# include <initializer_list>
463-
# include <iterator>
457+
# include <iterator> // some CPOs are provided in <iterator> per [range.access.general]
464458

465459
// [tuple.helper]
466460
# include <__tuple/tuple_element.h>

libcxx/test/std/library/description/conventions/customization.point.object/cpo.compile.pass.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ static_assert(test(std::ranges::rend, a));
8181
static_assert(test(std::ranges::size, a));
8282
static_assert(test(std::ranges::ssize, a));
8383

84+
#if TEST_STD_VER >= 26
85+
// static_assert(test(std::views::reserve_hint, a));
86+
#endif
87+
8488
// [range.factories]
8589
// views::empty<T> is not a CPO
8690
static_assert(test(std::views::iota, 1));
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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+
// REQUIRES: std-at-least-c++20
10+
11+
// [range.access.general]/1:
12+
// In addition to being available via inclusion of the <ranges> header, the customization point objects in
13+
// [range.access] are available when the header <iterator> is included.
14+
15+
#include <iterator>
16+
#include <type_traits>
17+
18+
#include "test_macros.h"
19+
20+
template <class CPO, class... Args>
21+
constexpr bool test(CPO& o, Args&&...) {
22+
static_assert(std::is_const_v<CPO>);
23+
static_assert(std::is_class_v<CPO>);
24+
static_assert(std::is_trivially_copyable_v<CPO>);
25+
static_assert(std::is_trivially_default_constructible_v<CPO>);
26+
27+
auto p = o;
28+
using T = decltype(p);
29+
30+
// The type of a customization point object, ignoring cv-qualifiers, shall model semiregular.
31+
static_assert(std::semiregular<T>);
32+
33+
// The type T of a customization point object, ignoring cv-qualifiers, shall model...
34+
static_assert(std::invocable<T&, Args...>);
35+
static_assert(std::invocable<const T&, Args...>);
36+
static_assert(std::invocable<T, Args...>);
37+
static_assert(std::invocable<const T, Args...>);
38+
39+
return true;
40+
}
41+
42+
int a[10];
43+
44+
static_assert(test(std::ranges::begin, a));
45+
static_assert(test(std::ranges::end, a));
46+
static_assert(test(std::ranges::cbegin, a));
47+
static_assert(test(std::ranges::cdata, a));
48+
static_assert(test(std::ranges::cend, a));
49+
static_assert(test(std::ranges::crbegin, a));
50+
static_assert(test(std::ranges::crend, a));
51+
static_assert(test(std::ranges::data, a));
52+
static_assert(test(std::ranges::empty, a));
53+
static_assert(test(std::ranges::rbegin, a));
54+
static_assert(test(std::ranges::rend, a));
55+
static_assert(test(std::ranges::size, a));
56+
static_assert(test(std::ranges::ssize, a));
57+
58+
#if TEST_STD_VER >= 26
59+
// static_assert(test(std::views::reserve_hint, a));
60+
#endif

0 commit comments

Comments
 (0)