Skip to content

Commit d4f2563

Browse files
[libc++] Support sorting consteval-only ranges
In [P2996R11](https://isocpp.org/files/papers/P2996R11.html), it is reported that libc++'s `sort` mechanisms eventually instantiate some non-`constexpr` function templates, which will be ill-fomred for `consteval`-only `std::meta::info`. Unfortunately, such ill-formedness can be reproduced in C++20 with DRs, e.g., by an iterator type which only supports `consteval` operations. This patch fixes that issue by making non-`constexpr` branches (since C++20) only contain externally instiantiated `__sort` specializations. This also makes `sort` perform the same operations at compile time and run time. Drive-by: Enables test cases for `ranges::sort` with proxy iterators.
1 parent ad9f15a commit d4f2563

File tree

6 files changed

+357
-67
lines changed

6 files changed

+357
-67
lines changed

libcxx/include/__algorithm/sort.h

Lines changed: 75 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@
1717
#include <__algorithm/partial_sort.h>
1818
#include <__algorithm/unwrap_iter.h>
1919
#include <__assert>
20+
#include <__bit/bit_log2.h>
2021
#include <__bit/blsr.h>
2122
#include <__bit/countl.h>
2223
#include <__bit/countr.h>
2324
#include <__config>
25+
#include <__cstddef/ptrdiff_t.h>
26+
#include <__cstddef/size_t.h>
2427
#include <__debug_utils/randomize_range.h>
2528
#include <__debug_utils/strict_weak_ordering_check.h>
2629
#include <__functional/operations.h>
@@ -34,6 +37,7 @@
3437
#include <__type_traits/is_constant_evaluated.h>
3538
#include <__type_traits/is_same.h>
3639
#include <__type_traits/is_trivially_copyable.h>
40+
#include <__type_traits/make_unsigned.h>
3741
#include <__utility/move.h>
3842
#include <__utility/pair.h>
3943
#include <climits>
@@ -138,7 +142,7 @@ template <class,
138142
class _Compare,
139143
class _RandomAccessIterator,
140144
__enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0>
141-
inline _LIBCPP_HIDE_FROM_ABI void
145+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
142146
__sort4(_RandomAccessIterator __x1,
143147
_RandomAccessIterator __x2,
144148
_RandomAccessIterator __x3,
@@ -155,7 +159,7 @@ template <class _AlgPolicy,
155159
class _Compare,
156160
class _RandomAccessIterator,
157161
__enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0>
158-
inline _LIBCPP_HIDE_FROM_ABI void
162+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
159163
__sort4(_RandomAccessIterator __x1,
160164
_RandomAccessIterator __x2,
161165
_RandomAccessIterator __x3,
@@ -180,7 +184,7 @@ template <class _AlgPolicy,
180184
class _Compare,
181185
class _RandomAccessIterator,
182186
__enable_if_t<__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0>
183-
inline _LIBCPP_HIDE_FROM_ABI void
187+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
184188
__sort5(_RandomAccessIterator __x1,
185189
_RandomAccessIterator __x2,
186190
_RandomAccessIterator __x3,
@@ -199,7 +203,7 @@ template <class _AlgPolicy,
199203
class _Compare,
200204
class _RandomAccessIterator,
201205
__enable_if_t<!__use_branchless_sort<_Compare, _RandomAccessIterator>, int> = 0>
202-
inline _LIBCPP_HIDE_FROM_ABI void
206+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
203207
__sort5(_RandomAccessIterator __x1,
204208
_RandomAccessIterator __x2,
205209
_RandomAccessIterator __x3,
@@ -238,7 +242,7 @@ __selection_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
238242
// Sort the iterator range [__first, __last) using the comparator __comp using
239243
// the insertion sort algorithm.
240244
template <class _AlgPolicy, class _Compare, class _BidirectionalIterator>
241-
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 void
245+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
242246
__insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last, _Compare __comp) {
243247
using _Ops = _IterOps<_AlgPolicy>;
244248

@@ -268,7 +272,7 @@ __insertion_sort(_BidirectionalIterator __first, _BidirectionalIterator __last,
268272
// Assumes that there is an element in the position (__first - 1) and that each
269273
// element in the input range is greater or equal to the element at __first - 1.
270274
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
271-
_LIBCPP_HIDE_FROM_ABI void
275+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
272276
__insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIterator __last, _Compare __comp) {
273277
using _Ops = _IterOps<_AlgPolicy>;
274278
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -296,7 +300,7 @@ __insertion_sort_unguarded(_RandomAccessIterator const __first, _RandomAccessIte
296300
}
297301

298302
template <class _AlgPolicy, class _Comp, class _RandomAccessIterator>
299-
_LIBCPP_HIDE_FROM_ABI bool
303+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 bool
300304
__insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
301305
using _Ops = _IterOps<_AlgPolicy>;
302306

@@ -350,7 +354,7 @@ __insertion_sort_incomplete(_RandomAccessIterator __first, _RandomAccessIterator
350354
}
351355

352356
template <class _AlgPolicy, class _RandomAccessIterator>
353-
inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
357+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap_bitmap_pos(
354358
_RandomAccessIterator __first, _RandomAccessIterator __last, uint64_t& __left_bitset, uint64_t& __right_bitset) {
355359
using _Ops = _IterOps<_AlgPolicy>;
356360
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -368,7 +372,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos(
368372
template <class _Compare,
369373
class _RandomAccessIterator,
370374
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
371-
inline _LIBCPP_HIDE_FROM_ABI void
375+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
372376
__populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueType& __pivot, uint64_t& __left_bitset) {
373377
// Possible vectorization. With a proper "-march" flag, the following loop
374378
// will be compiled into a set of SIMD instructions.
@@ -384,7 +388,7 @@ __populate_left_bitset(_RandomAccessIterator __first, _Compare __comp, _ValueTyp
384388
template <class _Compare,
385389
class _RandomAccessIterator,
386390
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
387-
inline _LIBCPP_HIDE_FROM_ABI void
391+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
388392
__populate_right_bitset(_RandomAccessIterator __lm1, _Compare __comp, _ValueType& __pivot, uint64_t& __right_bitset) {
389393
// Possible vectorization. With a proper "-march" flag, the following loop
390394
// will be compiled into a set of SIMD instructions.
@@ -401,7 +405,7 @@ template <class _AlgPolicy,
401405
class _Compare,
402406
class _RandomAccessIterator,
403407
class _ValueType = typename iterator_traits<_RandomAccessIterator>::value_type>
404-
inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks(
408+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __bitset_partition_partial_blocks(
405409
_RandomAccessIterator& __first,
406410
_RandomAccessIterator& __lm1,
407411
_Compare __comp,
@@ -448,7 +452,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __bitset_partition_partial_blocks(
448452
}
449453

450454
template <class _AlgPolicy, class _RandomAccessIterator>
451-
inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
455+
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __swap_bitmap_pos_within(
452456
_RandomAccessIterator& __first, _RandomAccessIterator& __lm1, uint64_t& __left_bitset, uint64_t& __right_bitset) {
453457
using _Ops = _IterOps<_AlgPolicy>;
454458
typedef typename std::iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -489,7 +493,7 @@ inline _LIBCPP_HIDE_FROM_ABI void __swap_bitmap_pos_within(
489493
// __bitset_partition uses bitsets for storing outcomes of the comparisons
490494
// between the pivot and other elements.
491495
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
492-
_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
496+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_RandomAccessIterator, bool>
493497
__bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
494498
using _Ops = _IterOps<_AlgPolicy>;
495499
typedef typename std::iterator_traits<_RandomAccessIterator>::value_type value_type;
@@ -581,7 +585,7 @@ __bitset_partition(_RandomAccessIterator __first, _RandomAccessIterator __last,
581585
// the provided range is already sorted, false otherwise. We assume that the
582586
// length of the range is at least three elements.
583587
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
584-
_LIBCPP_HIDE_FROM_ABI std::pair<_RandomAccessIterator, bool>
588+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 std::pair<_RandomAccessIterator, bool>
585589
__partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
586590
using _Ops = _IterOps<_AlgPolicy>;
587591
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -649,7 +653,7 @@ __partition_with_equals_on_right(_RandomAccessIterator __first, _RandomAccessIte
649653
// Similar to the above function. Elements equivalent to the pivot are put to
650654
// the left of the pivot. Returns the iterator to the pivot element.
651655
template <class _AlgPolicy, class _RandomAccessIterator, class _Compare>
652-
_LIBCPP_HIDE_FROM_ABI _RandomAccessIterator
656+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _RandomAccessIterator
653657
__partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIterator __last, _Compare __comp) {
654658
using _Ops = _IterOps<_AlgPolicy>;
655659
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
@@ -712,11 +716,12 @@ __partition_with_equals_on_left(_RandomAccessIterator __first, _RandomAccessIter
712716
// The implementation is partly based on Orson Peters' pattern-defeating
713717
// quicksort, published at: <https://github.com/orlp/pdqsort>.
714718
template <class _AlgPolicy, class _Compare, class _RandomAccessIterator, bool _UseBitSetPartition>
715-
void __introsort(_RandomAccessIterator __first,
716-
_RandomAccessIterator __last,
717-
_Compare __comp,
718-
typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
719-
bool __leftmost = true) {
719+
_LIBCPP_CONSTEXPR_SINCE_CXX20 void
720+
__introsort(_RandomAccessIterator __first,
721+
_RandomAccessIterator __last,
722+
_Compare __comp,
723+
typename iterator_traits<_RandomAccessIterator>::difference_type __depth,
724+
bool __leftmost = true) {
720725
using _Ops = _IterOps<_AlgPolicy>;
721726
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
722727
using _Comp_ref = __comp_ref_type<_Compare>;
@@ -826,25 +831,6 @@ void __introsort(_RandomAccessIterator __first,
826831
}
827832
}
828833

829-
template <typename _Number>
830-
inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) {
831-
if (__n == 0)
832-
return 0;
833-
if (sizeof(__n) <= sizeof(unsigned))
834-
return sizeof(unsigned) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned>(__n));
835-
if (sizeof(__n) <= sizeof(unsigned long))
836-
return sizeof(unsigned long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long>(__n));
837-
if (sizeof(__n) <= sizeof(unsigned long long))
838-
return sizeof(unsigned long long) * CHAR_BIT - 1 - __libcpp_clz(static_cast<unsigned long long>(__n));
839-
840-
_Number __log2 = 0;
841-
while (__n > 1) {
842-
__log2++;
843-
__n >>= 1;
844-
}
845-
return __log2;
846-
}
847-
848834
template <class _Comp, class _RandomAccessIterator>
849835
void __sort(_RandomAccessIterator, _RandomAccessIterator, _Comp);
850836

@@ -877,8 +863,10 @@ __sort<__less<long double>&, long double*>(long double*, long double*, __less<lo
877863
template <class _AlgPolicy, class _RandomAccessIterator, class _Comp>
878864
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
879865
__sort_dispatch(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
880-
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
881-
difference_type __depth_limit = 2 * std::__log2i(__last - __first);
866+
using difference_type = typename iterator_traits<_RandomAccessIterator>::difference_type;
867+
using __size_type = __make_unsigned_t<difference_type>;
868+
difference_type __depth_limit =
869+
static_cast<difference_type>(2 * std::__bit_log2(static_cast<__size_type>(__last - __first)));
882870

883871
// Only use bitset partitioning for arithmetic types. We should also check
884872
// that the default comparator is in use so that we are sure that there are no
@@ -912,30 +900,63 @@ using __sort_is_specialized_in_library _LIBCPP_NODEBUG = __is_any_of<
912900
long double>;
913901

914902
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
915-
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) {
916-
__less<_Type> __comp;
917-
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
903+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_Type* __first, _Type* __last, __less<>&) {
904+
#if _LIBCPP_STD_VER >= 20
905+
if (std::is_constant_evaluated()) {
906+
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first)));
907+
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
908+
__first, __last, ranges::less{}, __depth_limit);
909+
} else
910+
#endif
911+
{
912+
__less<_Type> __comp;
913+
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
914+
}
918915
}
919916

920917
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
921-
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) {
922-
__less<_Type> __comp;
923-
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
918+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_Type* __first, _Type* __last, less<_Type>&) {
919+
#if _LIBCPP_STD_VER >= 20
920+
if (std::is_constant_evaluated()) {
921+
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first)));
922+
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
923+
__first, __last, ranges::less{}, __depth_limit);
924+
} else
925+
#endif
926+
{
927+
__less<_Type> __comp;
928+
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
929+
}
924930
}
925931

926932
#if _LIBCPP_STD_VER >= 14
927933
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
928-
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, less<>&) {
929-
__less<_Type> __comp;
930-
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
934+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __sort_dispatch(_Type* __first, _Type* __last, less<>&) {
935+
# if _LIBCPP_STD_VER >= 20
936+
if (std::is_constant_evaluated()) {
937+
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first)));
938+
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
939+
__first, __last, ranges::less{}, __depth_limit);
940+
} else
941+
# endif
942+
{
943+
__less<_Type> __comp;
944+
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
945+
}
931946
}
932947
#endif
933948

934949
#if _LIBCPP_STD_VER >= 20
935950
template <class _AlgPolicy, class _Type, __enable_if_t<__sort_is_specialized_in_library<_Type>::value, int> = 0>
936-
_LIBCPP_HIDE_FROM_ABI void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) {
937-
__less<_Type> __comp;
938-
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
951+
_LIBCPP_HIDE_FROM_ABI constexpr void __sort_dispatch(_Type* __first, _Type* __last, ranges::less&) {
952+
if (std::is_constant_evaluated()) {
953+
auto __depth_limit = static_cast<ptrdiff_t>(2 * std::__bit_log2(static_cast<size_t>(__last - __first)));
954+
std::__introsort<_ClassicAlgPolicy, ranges::less, _Type*, __use_branchless_sort<ranges::less, _Type*>>(
955+
__first, __last, ranges::less{}, __depth_limit);
956+
} else {
957+
__less<_Type> __comp;
958+
std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
959+
}
939960
}
940961
#endif
941962

@@ -944,12 +965,7 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
944965
__sort_impl(_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
945966
std::__debug_randomize_range<_AlgPolicy>(__first, __last);
946967

947-
if (__libcpp_is_constant_evaluated()) {
948-
std::__partial_sort<_AlgPolicy>(
949-
std::__unwrap_iter(__first), std::__unwrap_iter(__last), std::__unwrap_iter(__last), __comp);
950-
} else {
951-
std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp);
952-
}
968+
std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp);
953969
std::__check_strict_weak_ordering_sorted(std::__unwrap_iter(__first), std::__unwrap_iter(__last), __comp);
954970
}
955971

libcxx/include/__bit/bit_log2.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,12 @@
2020

2121
_LIBCPP_BEGIN_NAMESPACE_STD
2222

23-
#if _LIBCPP_STD_VER >= 14
24-
2523
template <class _Tp>
26-
_LIBCPP_HIDE_FROM_ABI constexpr _Tp __bit_log2(_Tp __t) noexcept {
24+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp __bit_log2(_Tp __t) _NOEXCEPT {
2725
static_assert(__libcpp_is_unsigned_integer<_Tp>::value, "__bit_log2 requires an unsigned integer type");
2826
return numeric_limits<_Tp>::digits - 1 - std::__countl_zero(__t);
2927
}
3028

31-
#endif // _LIBCPP_STD_VER >= 14
32-
3329
_LIBCPP_END_NAMESPACE_STD
3430

3531
#endif // _LIBCPP___BIT_BIT_LOG2_H

libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/ranges.sort.pass.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,10 @@ constexpr void test_iterators() {
115115
test_iterators_1<random_access_iterator<int*>>();
116116
test_iterators_1<contiguous_iterator<int*>>();
117117
test_iterators_1<int*>();
118+
#if __cpp_consteval >= 202211L // TODO: Remove this guard when MSVC implements P2564R3.
119+
test_iterators_1<consteval_random_access_iterator<int*>>();
120+
test_iterators_1<consteval_contiguous_iterator<int*>>();
121+
#endif
118122
}
119123

120124
constexpr bool test() {
@@ -187,8 +191,6 @@ constexpr bool test() {
187191
[[maybe_unused]] std::same_as<std::ranges::dangling> decltype(auto) result = std::ranges::sort(std::array{1, 2, 3});
188192
}
189193

190-
// TODO: Enable the tests once the implementation switched to use iter_move/iter_swap
191-
/*
192194
{ // ProxyIterator
193195
{
194196
std::array in = {2, 1, 3};
@@ -205,7 +207,6 @@ constexpr bool test() {
205207
assert((in == std::array{1, 2, 3}));
206208
}
207209
}
208-
*/
209210

210211
return true;
211212
}

libcxx/test/std/algorithms/alg.sorting/alg.sort/sort/sort_constexpr.pass.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,39 @@ int main(int, char**)
112112
static_assert(test_pointers<17, int, int**>());
113113
static_assert(test_pointers<17, int, random_access_iterator<int**>>());
114114
static_assert(test_pointers<17, int, contiguous_iterator<int**>>());
115+
116+
// Test consteval-only operations
117+
# if __cpp_consteval >= 202211L // TODO: Remove this guard when MSVC implements P2564R3.
118+
(void)test<7, int, consteval_random_access_iterator<int*>>();
119+
(void)test<7, int, consteval_contiguous_iterator<int*>>();
120+
(void)test<LargeN, int, consteval_random_access_iterator<int*>>();
121+
(void)test<LargeN, int, consteval_contiguous_iterator<int*>>();
122+
(void)test<7, MoveOnly, consteval_random_access_iterator<MoveOnly*>>();
123+
(void)test<7, MoveOnly, consteval_contiguous_iterator<MoveOnly*>>();
124+
(void)test<LargeN, MoveOnly, consteval_random_access_iterator<MoveOnly*>>();
125+
(void)test<LargeN, MoveOnly, consteval_contiguous_iterator<MoveOnly*>>();
126+
(void)test_pointers<17, char, consteval_random_access_iterator<char**>>();
127+
(void)test_pointers<17, char, consteval_contiguous_iterator<char**>>();
128+
(void)test_pointers<17, const char, consteval_random_access_iterator<const char**>>();
129+
(void)test_pointers<17, const char, consteval_contiguous_iterator<const char**>>();
130+
(void)test_pointers<17, int, consteval_random_access_iterator<int**>>();
131+
(void)test_pointers<17, int, consteval_contiguous_iterator<int**>>();
132+
133+
static_assert(test<7, int, consteval_random_access_iterator<int*>>());
134+
static_assert(test<7, int, consteval_contiguous_iterator<int*>>());
135+
static_assert(test<LargeN, int, consteval_random_access_iterator<int*>>());
136+
static_assert(test<LargeN, int, consteval_contiguous_iterator<int*>>());
137+
static_assert(test<7, MoveOnly, consteval_random_access_iterator<MoveOnly*>>());
138+
static_assert(test<7, MoveOnly, consteval_contiguous_iterator<MoveOnly*>>());
139+
static_assert(test<LargeN, MoveOnly, consteval_random_access_iterator<MoveOnly*>>());
140+
static_assert(test<LargeN, MoveOnly, consteval_contiguous_iterator<MoveOnly*>>());
141+
static_assert(test_pointers<17, char, consteval_random_access_iterator<char**>>());
142+
static_assert(test_pointers<17, char, consteval_contiguous_iterator<char**>>());
143+
static_assert(test_pointers<17, const char, consteval_random_access_iterator<const char**>>());
144+
static_assert(test_pointers<17, const char, consteval_contiguous_iterator<const char**>>());
145+
static_assert(test_pointers<17, int, consteval_random_access_iterator<int**>>());
146+
static_assert(test_pointers<17, int, consteval_contiguous_iterator<int**>>());
147+
# endif
115148
#endif
116149

117150
return 0;

0 commit comments

Comments
 (0)