29
29
#include < __memory/destruct_n.h>
30
30
#include < __memory/unique_ptr.h>
31
31
#include < __type_traits/conditional.h>
32
+ #include < __type_traits/disjunction.h>
32
33
#include < __type_traits/is_arithmetic.h>
33
34
#include < __utility/move.h>
34
35
#include < __utility/pair.h>
41
42
42
43
_LIBCPP_BEGIN_NAMESPACE_STD
43
44
44
- // Wraps an algorithm policy tag and a comparator in a single struct, used to pass the policy tag around without
45
- // changing the number of template arguments (to keep the ABI stable). This is only used for the "range" policy tag.
46
- //
47
- // To create an object of this type, use `_WrapAlgPolicy<T, C>::type` -- see the specialization below for the rationale.
48
- template <class _PolicyT , class _CompT , class = void >
49
- struct _WrapAlgPolicy {
50
- using type = _WrapAlgPolicy;
51
-
52
- using _AlgPolicy = _PolicyT;
53
- using _Comp = _CompT;
54
- _Comp& __comp;
55
-
56
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
57
- _WrapAlgPolicy (_Comp& __c) : __comp(__c) {}
58
- };
59
-
60
- // Specialization for the "classic" policy tag that avoids creating a struct and simply defines an alias for the
61
- // comparator. When unwrapping, a pristine comparator is always considered to have the "classic" tag attached. Passing
62
- // the pristine comparator where possible allows using template instantiations from the dylib.
63
- template <class _PolicyT , class _CompT >
64
- struct _WrapAlgPolicy <_PolicyT, _CompT, __enable_if_t <std::is_same<_PolicyT, _ClassicAlgPolicy>::value> > {
65
- using type = _CompT;
66
- };
67
-
68
- // Unwraps a pristine functor (e.g. `std::less`) as if it were wrapped using `_WrapAlgPolicy`. The policy tag is always
69
- // set to "classic".
70
- template <class _CompT >
71
- struct _UnwrapAlgPolicy {
72
- using _AlgPolicy = _ClassicAlgPolicy;
73
- using _Comp = _CompT;
74
-
75
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
76
- _Comp __get_comp (_Comp __comp) { return __comp; }
77
- };
78
-
79
- // Unwraps a `_WrapAlgPolicy` struct.
80
- template <class ... _Ts>
81
- struct _UnwrapAlgPolicy <_WrapAlgPolicy<_Ts...> > {
82
- using _Wrapped = _WrapAlgPolicy<_Ts...>;
83
- using _AlgPolicy = typename _Wrapped::_AlgPolicy;
84
- using _Comp = typename _Wrapped::_Comp;
85
-
86
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 static
87
- _Comp __get_comp (_Wrapped& __w) { return __w.__comp ; }
88
- };
89
-
90
45
// stable, 2-3 compares, 0-2 swaps
91
46
92
47
template <class _AlgPolicy , class _Compare , class _ForwardIterator >
@@ -151,27 +106,22 @@ unsigned __sort4(_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator
151
106
152
107
// stable, 4-10 compares, 0-9 swaps
153
108
154
- template <class _WrappedComp , class _ForwardIterator >
155
- _LIBCPP_HIDDEN unsigned __sort5 (_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3,
156
- _ForwardIterator __x4, _ForwardIterator __x5, _WrappedComp __wrapped_comp) {
157
- using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>;
158
- using _AlgPolicy = typename _Unwrap::_AlgPolicy;
109
+ template <class _AlgPolicy , class _Comp , class _ForwardIterator >
110
+ _LIBCPP_HIDE_FROM_ABI unsigned __sort5 (_ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3,
111
+ _ForwardIterator __x4, _ForwardIterator __x5, _Comp __comp) {
159
112
using _Ops = _IterOps<_AlgPolicy>;
160
113
161
- using _Compare = typename _Unwrap::_Comp;
162
- _Compare __c = _Unwrap::__get_comp (__wrapped_comp);
163
-
164
- unsigned __r = std::__sort4<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __c);
165
- if (__c (*__x5, *__x4)) {
114
+ unsigned __r = std::__sort4<_AlgPolicy, _Comp>(__x1, __x2, __x3, __x4, __comp);
115
+ if (__comp (*__x5, *__x4)) {
166
116
_Ops::iter_swap (__x4, __x5);
167
117
++__r;
168
- if (__c (*__x4, *__x3)) {
118
+ if (__comp (*__x4, *__x3)) {
169
119
_Ops::iter_swap (__x3, __x4);
170
120
++__r;
171
- if (__c (*__x3, *__x2)) {
121
+ if (__comp (*__x3, *__x2)) {
172
122
_Ops::iter_swap (__x2, __x3);
173
123
++__r;
174
- if (__c (*__x2, *__x1)) {
124
+ if (__comp (*__x2, *__x1)) {
175
125
_Ops::iter_swap (__x1, __x2);
176
126
++__r;
177
127
}
@@ -181,16 +131,6 @@ _LIBCPP_HIDDEN unsigned __sort5(_ForwardIterator __x1, _ForwardIterator __x2, _F
181
131
return __r;
182
132
}
183
133
184
- template <class _AlgPolicy , class _Compare , class _ForwardIterator >
185
- _LIBCPP_HIDE_FROM_ABI unsigned __sort5_wrap_policy (
186
- _ForwardIterator __x1, _ForwardIterator __x2, _ForwardIterator __x3, _ForwardIterator __x4, _ForwardIterator __x5,
187
- _Compare __c) {
188
- using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type;
189
- _WrappedComp __wrapped_comp (__c);
190
- return std::__sort5<_WrappedComp, _ForwardIterator>(
191
- std::move (__x1), std::move (__x2), std::move (__x3), std::move (__x4), std::move (__x5), __wrapped_comp);
192
- }
193
-
194
134
// The comparator being simple is a prerequisite for using the branchless optimization.
195
135
template <class _Tp >
196
136
struct __is_simple_comparator : false_type {};
@@ -299,7 +239,8 @@ template <class _AlgPolicy, class _Compare, class _RandomAccessIterator>
299
239
inline _LIBCPP_HIDE_FROM_ABI __enable_if_t <!__use_branchless_sort<_Compare, _RandomAccessIterator>::value, void >
300
240
__sort5_maybe_branchless (_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3,
301
241
_RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) {
302
- std::__sort5_wrap_policy<_AlgPolicy, _Compare>(__x1, __x2, __x3, __x4, __x5, __c);
242
+ std::__sort5<_AlgPolicy, _Compare, _RandomAccessIterator>(
243
+ std::move (__x1), std::move (__x2), std::move (__x3), std::move (__x4), std::move (__x5), __c);
303
244
}
304
245
305
246
// Assumes size > 0
@@ -370,16 +311,11 @@ __insertion_sort_unguarded(_RandomAccessIterator __first, _RandomAccessIterator
370
311
}
371
312
}
372
313
373
- template <class _WrappedComp , class _RandomAccessIterator >
374
- _LIBCPP_HIDDEN bool __insertion_sort_incomplete (
375
- _RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) {
376
- using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>;
377
- using _AlgPolicy = typename _Unwrap::_AlgPolicy;
314
+ template <class _AlgPolicy , class _Comp , class _RandomAccessIterator >
315
+ _LIBCPP_HIDE_FROM_ABI bool __insertion_sort_incomplete (
316
+ _RandomAccessIterator __first, _RandomAccessIterator __last, _Comp __comp) {
378
317
using _Ops = _IterOps<_AlgPolicy>;
379
318
380
- using _Compare = typename _Unwrap::_Comp;
381
- _Compare __comp = _Unwrap::__get_comp (__wrapped_comp);
382
-
383
319
typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
384
320
switch (__last - __first) {
385
321
case 0 :
@@ -390,21 +326,21 @@ _LIBCPP_HIDDEN bool __insertion_sort_incomplete(
390
326
_Ops::iter_swap (__first, __last);
391
327
return true ;
392
328
case 3 :
393
- std::__sort3_maybe_branchless<_AlgPolicy, _Compare >(__first, __first + difference_type (1 ), --__last, __comp);
329
+ std::__sort3_maybe_branchless<_AlgPolicy, _Comp >(__first, __first + difference_type (1 ), --__last, __comp);
394
330
return true ;
395
331
case 4 :
396
- std::__sort4_maybe_branchless<_AlgPolicy, _Compare >(
332
+ std::__sort4_maybe_branchless<_AlgPolicy, _Comp >(
397
333
__first, __first + difference_type (1 ), __first + difference_type (2 ), --__last, __comp);
398
334
return true ;
399
335
case 5 :
400
- std::__sort5_maybe_branchless<_AlgPolicy, _Compare >(
336
+ std::__sort5_maybe_branchless<_AlgPolicy, _Comp >(
401
337
__first, __first + difference_type (1 ), __first + difference_type (2 ), __first + difference_type (3 ),
402
338
--__last, __comp);
403
339
return true ;
404
340
}
405
341
typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type;
406
342
_RandomAccessIterator __j = __first + difference_type (2 );
407
- std::__sort3_maybe_branchless<_AlgPolicy, _Compare >(__first, __first + difference_type (1 ), __j, __comp);
343
+ std::__sort3_maybe_branchless<_AlgPolicy, _Comp >(__first, __first + difference_type (1 ), __j, __comp);
408
344
const unsigned __limit = 8 ;
409
345
unsigned __count = 0 ;
410
346
for (_RandomAccessIterator __i = __j + difference_type (1 ); __i != __last; ++__i) {
@@ -862,10 +798,8 @@ void __introsort(_RandomAccessIterator __first,
862
798
// [__first, __i) < *__i and *__i <= [__i+1, __last)
863
799
// If we were given a perfect partition, see if insertion sort is quick...
864
800
if (__ret.second ) {
865
- using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Compare>::type;
866
- _WrappedComp __wrapped_comp (__comp);
867
- bool __fs = std::__insertion_sort_incomplete<_WrappedComp>(__first, __i, __wrapped_comp);
868
- if (std::__insertion_sort_incomplete<_WrappedComp>(__i + difference_type (1 ), __last, __wrapped_comp)) {
801
+ bool __fs = std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__first, __i, __comp);
802
+ if (std::__insertion_sort_incomplete<_AlgPolicy, _Compare>(__i + difference_type (1 ), __last, __comp)) {
869
803
if (__fs)
870
804
return ;
871
805
__last = __i;
@@ -904,30 +838,8 @@ inline _LIBCPP_HIDE_FROM_ABI _Number __log2i(_Number __n) {
904
838
return __log2;
905
839
}
906
840
907
- template <class _WrappedComp , class _RandomAccessIterator >
908
- _LIBCPP_HIDDEN void __sort (_RandomAccessIterator __first, _RandomAccessIterator __last, _WrappedComp __wrapped_comp) {
909
- typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
910
- difference_type __depth_limit = 2 * std::__log2i (__last - __first);
911
-
912
- using _Unwrap = _UnwrapAlgPolicy<_WrappedComp>;
913
- using _AlgPolicy = typename _Unwrap::_AlgPolicy;
914
- using _Compare = typename _Unwrap::_Comp;
915
- _Compare __comp = _Unwrap::__get_comp (__wrapped_comp);
916
- // Only use bitset partitioning for arithmetic types. We should also check
917
- // that the default comparator is in use so that we are sure that there are no
918
- // branches in the comparator.
919
- std::__introsort<_AlgPolicy,
920
- _Compare,
921
- _RandomAccessIterator,
922
- __use_branchless_sort<_Compare, _RandomAccessIterator>::value>(
923
- __first, __last, __comp, __depth_limit);
924
- }
925
-
926
- template <class _Compare , class _Tp >
927
- inline _LIBCPP_INLINE_VISIBILITY void __sort (_Tp** __first, _Tp** __last, __less<_Tp*>&) {
928
- __less<uintptr_t > __comp;
929
- std::__sort<__less<uintptr_t >&, uintptr_t *>((uintptr_t *)__first, (uintptr_t *)__last, __comp);
930
- }
841
+ template <class _Comp , class _RandomAccessIterator >
842
+ void __sort (_RandomAccessIterator, _RandomAccessIterator, _Comp);
931
843
932
844
extern template _LIBCPP_FUNC_VIS void __sort<__less<char >&, char *>(char *, char *, __less<char >&);
933
845
#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
@@ -947,20 +859,83 @@ extern template _LIBCPP_FUNC_VIS void __sort<__less<float>&, float*>(float*, flo
947
859
extern template _LIBCPP_FUNC_VIS void __sort<__less<double >&, double *>(double *, double *, __less<double >&);
948
860
extern template _LIBCPP_FUNC_VIS void __sort<__less<long double >&, long double *>(long double *, long double *, __less<long double >&);
949
861
862
+ template <class _AlgPolicy , class _RandomAccessIterator , class _Comp >
863
+ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void
864
+ __sort_dispatch (_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
865
+ typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type;
866
+ difference_type __depth_limit = 2 * std::__log2i (__last - __first);
867
+
868
+ // Only use bitset partitioning for arithmetic types. We should also check
869
+ // that the default comparator is in use so that we are sure that there are no
870
+ // branches in the comparator.
871
+ std::__introsort<_AlgPolicy,
872
+ _Comp&,
873
+ _RandomAccessIterator,
874
+ __use_branchless_sort<_Comp, _RandomAccessIterator>::value>(
875
+ __first, __last, __comp, __depth_limit);
876
+ }
877
+
878
+ template <class _Type , class ... _Options>
879
+ using __is_any_of = _Or<is_same<_Type, _Options>...>;
880
+
881
+ template <class _Type >
882
+ using __sort_is_specialized_in_library = __is_any_of<
883
+ _Type,
884
+ char ,
885
+ #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
886
+ wchar_t ,
887
+ #endif
888
+ signed char ,
889
+ unsigned char ,
890
+ short ,
891
+ unsigned short ,
892
+ int ,
893
+ unsigned int ,
894
+ long ,
895
+ unsigned long ,
896
+ long long ,
897
+ unsigned long long ,
898
+ float ,
899
+ double ,
900
+ long double >;
901
+
902
+ template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
903
+ _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, __less<_Type>& __comp) {
904
+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
905
+ }
906
+
907
+ template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
908
+ _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, less<_Type>&) {
909
+ __less<_Type> __comp;
910
+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
911
+ }
912
+
913
+ #if _LIBCPP_STD_VER >= 14
914
+ 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);
918
+ }
919
+ #endif
920
+
921
+ #if _LIBCPP_STD_VER >= 20
922
+ template <class _AlgPolicy , class _Type , __enable_if_t <__sort_is_specialized_in_library<_Type>::value, int > = 0 >
923
+ _LIBCPP_HIDE_FROM_ABI void __sort_dispatch (_Type* __first, _Type* __last, ranges::less&) {
924
+ __less<_Type> __comp;
925
+ std::__sort<__less<_Type>&, _Type*>(__first, __last, __comp);
926
+ }
927
+ #endif
928
+
950
929
template <class _AlgPolicy , class _RandomAccessIterator , class _Comp >
951
930
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
952
931
void __sort_impl (_RandomAccessIterator __first, _RandomAccessIterator __last, _Comp& __comp) {
953
932
std::__debug_randomize_range<_AlgPolicy>(__first, __last);
954
933
955
- using _Comp_ref = __comp_ref_type<_Comp>;
956
934
if (__libcpp_is_constant_evaluated ()) {
957
- std::__partial_sort<_AlgPolicy>(__first, __last, __last, __comp);
958
-
935
+ std::__partial_sort<_AlgPolicy>(
936
+ std::__unwrap_iter (__first), std::__unwrap_iter (__last), std::__unwrap_iter (__last), __comp);
959
937
} else {
960
- using _WrappedComp = typename _WrapAlgPolicy<_AlgPolicy, _Comp_ref>::type;
961
- _Comp_ref __comp_ref (__comp);
962
- _WrappedComp __wrapped_comp (__comp_ref);
963
- std::__sort<_WrappedComp>(std::__unwrap_iter (__first), std::__unwrap_iter (__last), __wrapped_comp);
938
+ std::__sort_dispatch<_AlgPolicy>(std::__unwrap_iter (__first), std::__unwrap_iter (__last), __comp);
964
939
}
965
940
}
966
941
0 commit comments