diff --git a/libcxx/benchmarks/algorithms.bench.cpp b/libcxx/benchmarks/algorithms.bench.cpp --- a/libcxx/benchmarks/algorithms.bench.cpp +++ b/libcxx/benchmarks/algorithms.bench.cpp @@ -14,23 +14,17 @@ namespace { -enum class ValueType { Uint32, Uint64, Pair, Tuple, String }; -struct AllValueTypes : EnumValuesAsTuple { - static constexpr const char* Names[] = { - "uint32", "uint64", "pair", - "tuple", "string"}; +enum ValueType { Uint32, Uint64, Pair, Tuple, String, Float }; +struct AllValueTypes : EnumValuesAsTuple { + static constexpr const char* Names[] = {"uint32", "uint64", "pair", "tuple", + "string", "float"}; }; +using Types = std::tuple< uint32_t, uint64_t, std::pair, std::tuple, + std::string, float >; + template -using Value = std::conditional_t< - V() == ValueType::Uint32, uint32_t, - std::conditional_t< - V() == ValueType::Uint64, uint64_t, - std::conditional_t< - V() == ValueType::Pair, std::pair, - std::conditional_t, - std::string> > > >; +using Value = std::tuple_element_t<(int)V(), Types>; enum class Order { Random, diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h --- a/libcxx/include/__algorithm/sort.h +++ b/libcxx/include/__algorithm/sort.h @@ -123,6 +123,86 @@ return __r; } +template ::value_type> +using __use_branchless_sort = bool_constant< __is_cpp17_contiguous_iterator<_Iter>::value && + sizeof(_Tp) <= sizeof(void*) && is_arithmetic<_Tp>::value >; + +// Ensures that __c(*__x, *__y) is true by swapping *__x and *__y if necessary. +template +inline _LIBCPP_HIDE_FROM_ABI void __cond_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, _Compare __c) { + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + bool __r = __c(*__x, *__y); + value_type __tmp = __r ? *__x : *__y; + *__y = __r ? *__y : *__x; + *__x = __tmp; +} + +// Ensures that *__x, *__y and *__z are ordered according to the comparator __c, +// under the assumption that *__y and *__z are already ordered. +template +inline _LIBCPP_HIDE_FROM_ABI void __partially_sorted_swap(_RandomAccessIterator __x, _RandomAccessIterator __y, + _RandomAccessIterator __z, _Compare __c) { + using value_type = typename iterator_traits<_RandomAccessIterator>::value_type; + bool __r = __c(*__z, *__x); + value_type __tmp = __r ? *__z : *__x; + *__z = __r ? *__x : *__z; + __r = __c(__tmp, *__y); + *__x = __r ? *__x : *__y; + *__y = __r ? *__y : __tmp; +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_RandomAccessIterator>::value, void> +__sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _Compare __c) { + _VSTD::__cond_swap<_Compare>(__x2, __x3, __c); + _VSTD::__partially_sorted_swap<_Compare>(__x1, __x2, __x3, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> +__sort3_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _Compare __c) { + _VSTD::__sort3<_Compare>(__x1, __x2, __x3, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_RandomAccessIterator>::value, void> +__sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _Compare __c) { + _VSTD::__cond_swap<_Compare>(__x1, __x3, __c); + _VSTD::__cond_swap<_Compare>(__x2, __x4, __c); + _VSTD::__cond_swap<_Compare>(__x1, __x2, __c); + _VSTD::__cond_swap<_Compare>(__x3, __x4, __c); + _VSTD::__cond_swap<_Compare>(__x2, __x3, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> +__sort4_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _Compare __c) { + _VSTD::__sort4<_Compare>(__x1, __x2, __x3, __x4, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t<__use_branchless_sort<_RandomAccessIterator>::value, void> +__sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { + _VSTD::__cond_swap<_Compare>(__x1, __x2, __c); + _VSTD::__cond_swap<_Compare>(__x4, __x5, __c); + _VSTD::__partially_sorted_swap<_Compare>(__x3, __x4, __x5, __c); + _VSTD::__cond_swap<_Compare>(__x2, __x5, __c); + _VSTD::__partially_sorted_swap<_Compare>(__x1, __x3, __x4, __c); + _VSTD::__partially_sorted_swap<_Compare>(__x2, __x3, __x4, __c); +} + +template +inline _LIBCPP_HIDE_FROM_ABI __enable_if_t::value, void> +__sort5_maybe_branchless(_RandomAccessIterator __x1, _RandomAccessIterator __x2, _RandomAccessIterator __x3, + _RandomAccessIterator __x4, _RandomAccessIterator __x5, _Compare __c) { + _VSTD::__sort5<_Compare>(__x1, __x2, __x3, __x4, __x5, __c); +} + // Assumes size > 0 template _LIBCPP_CONSTEXPR_AFTER_CXX11 void @@ -163,7 +243,7 @@ typedef typename iterator_traits<_RandomAccessIterator>::difference_type difference_type; typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; _RandomAccessIterator __j = __first+difference_type(2); - _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), __j, __comp); + _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), __j, __comp); for (_RandomAccessIterator __i = __j+difference_type(1); __i != __last; ++__i) { if (__comp(*__i, *__j)) @@ -197,18 +277,20 @@ swap(*__first, *__last); return true; case 3: - _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), --__last, __comp); - return true; + _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), --__last, __comp); + return true; case 4: - _VSTD::__sort4<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), --__last, __comp); - return true; + _VSTD::__sort4_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), + --__last, __comp); + return true; case 5: - _VSTD::__sort5<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), __first+difference_type(3), --__last, __comp); - return true; + _VSTD::__sort5_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), + __first + difference_type(3), --__last, __comp); + return true; } typedef typename iterator_traits<_RandomAccessIterator>::value_type value_type; _RandomAccessIterator __j = __first+difference_type(2); - _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), __j, __comp); + _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), __j, __comp); const unsigned __limit = 8; unsigned __count = 0; for (_RandomAccessIterator __i = __j+difference_type(1); __i != __last; ++__i) @@ -290,14 +372,16 @@ swap(*__first, *__last); return; case 3: - _VSTD::__sort3<_Compare>(__first, __first+difference_type(1), --__last, __comp); - return; + _VSTD::__sort3_maybe_branchless<_Compare>(__first, __first + difference_type(1), --__last, __comp); + return; case 4: - _VSTD::__sort4<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), --__last, __comp); - return; + _VSTD::__sort4_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), + --__last, __comp); + return; case 5: - _VSTD::__sort5<_Compare>(__first, __first+difference_type(1), __first+difference_type(2), __first+difference_type(3), --__last, __comp); - return; + _VSTD::__sort5_maybe_branchless<_Compare>(__first, __first + difference_type(1), __first + difference_type(2), + __first + difference_type(3), --__last, __comp); + return; } if (__len <= __limit) { diff --git a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp --- a/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp +++ b/libcxx/test/libcxx/algorithms/robust_against_copying_comparators.pass.cpp @@ -14,176 +14,189 @@ #include "test_macros.h" +template struct Less { int *copies_; TEST_CONSTEXPR explicit Less(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 Less(const Less& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 Less& operator=(const Less&) = default; - TEST_CONSTEXPR bool operator()(void*, void*) const { return false; } + TEST_CONSTEXPR bool operator()(T, T) const { return false; } }; +template struct Equal { int *copies_; TEST_CONSTEXPR explicit Equal(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 Equal(const Equal& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 Equal& operator=(const Equal&) = default; - TEST_CONSTEXPR bool operator()(void*, void*) const { return true; } + TEST_CONSTEXPR bool operator()(T, T) const { return true; } }; +template struct UnaryVoid { int *copies_; TEST_CONSTEXPR explicit UnaryVoid(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 UnaryVoid(const UnaryVoid& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 UnaryVoid& operator=(const UnaryVoid&) = default; - TEST_CONSTEXPR_CXX14 void operator()(void*) const {} + TEST_CONSTEXPR_CXX14 void operator()(T) const {} }; +template struct UnaryTrue { int *copies_; TEST_CONSTEXPR explicit UnaryTrue(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 UnaryTrue(const UnaryTrue& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 UnaryTrue& operator=(const UnaryTrue&) = default; - TEST_CONSTEXPR bool operator()(void*) const { return true; } + TEST_CONSTEXPR bool operator()(T) const { return true; } }; +template struct NullaryValue { int *copies_; TEST_CONSTEXPR explicit NullaryValue(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 NullaryValue(const NullaryValue& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 NullaryValue& operator=(const NullaryValue&) = default; - TEST_CONSTEXPR std::nullptr_t operator()() const { return nullptr; } + TEST_CONSTEXPR T operator()() const { return 0; } }; +template struct UnaryTransform { int *copies_; TEST_CONSTEXPR explicit UnaryTransform(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 UnaryTransform(const UnaryTransform& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 UnaryTransform& operator=(const UnaryTransform&) = default; - TEST_CONSTEXPR std::nullptr_t operator()(void*) const { return nullptr; } + TEST_CONSTEXPR T operator()(T) const { return 0; } }; +template struct BinaryTransform { int *copies_; TEST_CONSTEXPR explicit BinaryTransform(int *copies) : copies_(copies) {} TEST_CONSTEXPR_CXX14 BinaryTransform(const BinaryTransform& rhs) : copies_(rhs.copies_) { *copies_ += 1; } TEST_CONSTEXPR_CXX14 BinaryTransform& operator=(const BinaryTransform&) = default; - TEST_CONSTEXPR std::nullptr_t operator()(void*, void*) const { return nullptr; } + TEST_CONSTEXPR T operator()(T, T) const { return 0; } }; +template TEST_CONSTEXPR_CXX20 bool all_the_algorithms() { - void *a[10] = {}; - void *b[10] = {}; - void **first = a; - void **mid = a+5; - void **last = a+10; - void **first2 = b; - void **mid2 = b+5; - void **last2 = b+10; - void *value = nullptr; + T a[10] = {}; + T b[10] = {}; + T *first = a; + T *mid = a+5; + T *last = a+10; + T *first2 = b; + T *mid2 = b+5; + T *last2 = b+10; + T value = 0; int count = 1; int copies = 0; - (void)std::adjacent_find(first, last, Equal(&copies)); assert(copies == 0); + (void)std::adjacent_find(first, last, Equal(&copies)); assert(copies == 0); #if TEST_STD_VER >= 11 - (void)std::all_of(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::any_of(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::all_of(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::any_of(first, last, UnaryTrue(&copies)); assert(copies == 0); #endif - (void)std::binary_search(first, last, value, Less(&copies)); assert(copies == 0); + (void)std::binary_search(first, last, value, Less(&copies)); assert(copies == 0); #if TEST_STD_VER > 17 - (void)std::clamp(value, value, value, Less(&copies)); assert(copies == 0); + (void)std::clamp(value, value, value, Less(&copies)); assert(copies == 0); #endif - (void)std::count_if(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::equal(first, last, first2, Equal(&copies)); assert(copies == 0); + (void)std::count_if(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::equal(first, last, first2, Equal(&copies)); assert(copies == 0); #if TEST_STD_VER > 11 - (void)std::equal(first, last, first2, last2, Equal(&copies)); assert(copies == 0); + (void)std::equal(first, last, first2, last2, Equal(&copies)); assert(copies == 0); #endif - (void)std::equal_range(first, last, value, Less(&copies)); assert(copies == 0); - (void)std::find_end(first, last, first2, mid2, Equal(&copies)); assert(copies == 0); - (void)std::find_if(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::find_if_not(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::for_each(first, last, UnaryVoid(&copies)); assert(copies == 1); copies = 0; + (void)std::equal_range(first, last, value, Less(&copies)); assert(copies == 0); + (void)std::find_end(first, last, first2, mid2, Equal(&copies)); assert(copies == 0); + (void)std::find_if(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::find_if_not(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::for_each(first, last, UnaryVoid(&copies)); assert(copies == 1); copies = 0; #if TEST_STD_VER > 14 - (void)std::for_each_n(first, count, UnaryVoid(&copies)); assert(copies == 0); + (void)std::for_each_n(first, count, UnaryVoid(&copies)); assert(copies == 0); #endif - (void)std::generate(first, last, NullaryValue(&copies)); assert(copies == 0); - (void)std::generate_n(first, count, NullaryValue(&copies)); assert(copies == 0); - (void)std::includes(first, last, first2, last2, Less(&copies)); assert(copies == 0); - (void)std::is_heap(first, last, Less(&copies)); assert(copies == 0); - (void)std::is_heap_until(first, last, Less(&copies)); assert(copies == 0); - (void)std::is_partitioned(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::is_permutation(first, last, first2, Equal(&copies)); assert(copies == 0); + (void)std::generate(first, last, NullaryValue(&copies)); assert(copies == 0); + (void)std::generate_n(first, count, NullaryValue(&copies)); assert(copies == 0); + (void)std::includes(first, last, first2, last2, Less(&copies)); assert(copies == 0); + (void)std::is_heap(first, last, Less(&copies)); assert(copies == 0); + (void)std::is_heap_until(first, last, Less(&copies)); assert(copies == 0); + (void)std::is_partitioned(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::is_permutation(first, last, first2, Equal(&copies)); assert(copies == 0); #if TEST_STD_VER > 11 - (void)std::is_permutation(first, last, first2, last2, Equal(&copies)); assert(copies == 0); + (void)std::is_permutation(first, last, first2, last2, Equal(&copies)); assert(copies == 0); #endif - (void)std::is_sorted(first, last, Less(&copies)); assert(copies == 0); - (void)std::is_sorted_until(first, last, Less(&copies)); assert(copies == 0); - if (!TEST_IS_CONSTANT_EVALUATED) { (void)std::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } - (void)std::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0); + (void)std::is_sorted(first, last, Less(&copies)); assert(copies == 0); + (void)std::is_sorted_until(first, last, Less(&copies)); assert(copies == 0); + if (!TEST_IS_CONSTANT_EVALUATED) { (void)std::inplace_merge(first, mid, last, Less(&copies)); assert(copies == 0); } + (void)std::lexicographical_compare(first, last, first2, last2, Less(&copies)); assert(copies == 0); // TODO: lexicographical_compare_three_way - (void)std::lower_bound(first, last, value, Less(&copies)); assert(copies == 0); - (void)std::make_heap(first, last, Less(&copies)); assert(copies == 0); - (void)std::max(value, value, Less(&copies)); assert(copies == 0); + (void)std::lower_bound(first, last, value, Less(&copies)); assert(copies == 0); + (void)std::make_heap(first, last, Less(&copies)); assert(copies == 0); + (void)std::max(value, value, Less(&copies)); assert(copies == 0); #if TEST_STD_VER >= 11 - (void)std::max({ value, value }, Less(&copies)); assert(copies == 0); + (void)std::max({ value, value }, Less(&copies)); assert(copies == 0); #endif - (void)std::max_element(first, last, Less(&copies)); assert(copies == 0); - (void)std::merge(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); - (void)std::min(value, value, Less(&copies)); assert(copies == 0); + (void)std::max_element(first, last, Less(&copies)); assert(copies == 0); + (void)std::merge(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); + (void)std::min(value, value, Less(&copies)); assert(copies == 0); #if TEST_STD_VER >= 11 - (void)std::min({ value, value }, Less(&copies)); assert(copies == 0); + (void)std::min({ value, value }, Less(&copies)); assert(copies == 0); #endif - (void)std::min_element(first, last, Less(&copies)); assert(copies == 0); - (void)std::minmax(value, value, Less(&copies)); assert(copies == 0); + (void)std::min_element(first, last, Less(&copies)); assert(copies == 0); + (void)std::minmax(value, value, Less(&copies)); assert(copies == 0); #if TEST_STD_VER >= 11 - (void)std::minmax({ value, value }, Less(&copies)); assert(copies == 0); + (void)std::minmax({ value, value }, Less(&copies)); assert(copies == 0); #endif - (void)std::minmax_element(first, last, Less(&copies)); assert(copies == 0); - (void)std::mismatch(first, last, first2, Equal(&copies)); assert(copies == 0); + (void)std::minmax_element(first, last, Less(&copies)); assert(copies == 0); + (void)std::mismatch(first, last, first2, Equal(&copies)); assert(copies == 0); #if TEST_STD_VER > 11 - (void)std::mismatch(first, last, first2, last2, Equal(&copies)); assert(copies == 0); + (void)std::mismatch(first, last, first2, last2, Equal(&copies)); assert(copies == 0); #endif - (void)std::next_permutation(first, last, Less(&copies)); assert(copies == 0); + (void)std::next_permutation(first, last, Less(&copies)); assert(copies == 0); #if TEST_STD_VER >= 11 - (void)std::none_of(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::none_of(first, last, UnaryTrue(&copies)); assert(copies == 0); #endif - (void)std::nth_element(first, mid, last, Less(&copies)); assert(copies == 0); - (void)std::partial_sort(first, mid, last, Less(&copies)); assert(copies == 0); - (void)std::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0); - (void)std::partition(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::partition_copy(first, last, first2, last2, UnaryTrue(&copies)); assert(copies == 0); - (void)std::partition_point(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::pop_heap(first, last, Less(&copies)); assert(copies == 0); - (void)std::prev_permutation(first, last, Less(&copies)); assert(copies == 0); - (void)std::push_heap(first, last, Less(&copies)); assert(copies == 0); - (void)std::remove_copy_if(first, last, first2, UnaryTrue(&copies)); assert(copies == 0); - (void)std::remove_if(first, last, UnaryTrue(&copies)); assert(copies == 0); - (void)std::replace_copy_if(first, last, first2, UnaryTrue(&copies), value); assert(copies == 0); - (void)std::replace_if(first, last, UnaryTrue(&copies), value); assert(copies == 0); - (void)std::search(first, last, first2, mid2, Equal(&copies)); assert(copies == 0); - (void)std::search_n(first, last, count, value, Equal(&copies)); assert(copies == 0); - (void)std::set_difference(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); - (void)std::set_intersection(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); - (void)std::set_symmetric_difference(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); - (void)std::set_union(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); - (void)std::sort(first, last, Less(&copies)); assert(copies == 0); - (void)std::sort_heap(first, last, Less(&copies)); assert(copies == 0); - if (!TEST_IS_CONSTANT_EVALUATED) { (void)std::stable_partition(first, last, UnaryTrue(&copies)); assert(copies == 0); } - if (!TEST_IS_CONSTANT_EVALUATED) { (void)std::stable_sort(first, last, Less(&copies)); assert(copies == 0); } - (void)std::transform(first, last, first2, UnaryTransform(&copies)); assert(copies == 0); - (void)std::transform(first, mid, mid, first2, BinaryTransform(&copies)); assert(copies == 0); - (void)std::unique(first, last, Equal(&copies)); assert(copies == 0); - (void)std::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0); - (void)std::upper_bound(first, last, value, Less(&copies)); assert(copies == 0); + (void)std::nth_element(first, mid, last, Less(&copies)); assert(copies == 0); + (void)std::partial_sort(first, mid, last, Less(&copies)); assert(copies == 0); + (void)std::partial_sort_copy(first, last, first2, mid2, Less(&copies)); assert(copies == 0); + (void)std::partition(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::partition_copy(first, last, first2, last2, UnaryTrue(&copies)); assert(copies == 0); + (void)std::partition_point(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::pop_heap(first, last, Less(&copies)); assert(copies == 0); + (void)std::prev_permutation(first, last, Less(&copies)); assert(copies == 0); + (void)std::push_heap(first, last, Less(&copies)); assert(copies == 0); + (void)std::remove_copy_if(first, last, first2, UnaryTrue(&copies)); assert(copies == 0); + (void)std::remove_if(first, last, UnaryTrue(&copies)); assert(copies == 0); + (void)std::replace_copy_if(first, last, first2, UnaryTrue(&copies), value); assert(copies == 0); + (void)std::replace_if(first, last, UnaryTrue(&copies), value); assert(copies == 0); + (void)std::search(first, last, first2, mid2, Equal(&copies)); assert(copies == 0); + (void)std::search_n(first, last, count, value, Equal(&copies)); assert(copies == 0); + (void)std::set_difference(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); + (void)std::set_intersection(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); + (void)std::set_symmetric_difference(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); + (void)std::set_union(first, mid, mid, last, first2, Less(&copies)); assert(copies == 0); + (void)std::sort(first, first+3, Less(&copies)); assert(copies == 0); + (void)std::sort(first, first+4, Less(&copies)); assert(copies == 0); + (void)std::sort(first, first+5, Less(&copies)); assert(copies == 0); + (void)std::sort(first, last, Less(&copies)); assert(copies == 0); + (void)std::sort_heap(first, last, Less(&copies)); assert(copies == 0); + if (!TEST_IS_CONSTANT_EVALUATED) { (void)std::stable_partition(first, last, UnaryTrue(&copies)); assert(copies == 0); } + if (!TEST_IS_CONSTANT_EVALUATED) { (void)std::stable_sort(first, last, Less(&copies)); assert(copies == 0); } + (void)std::transform(first, last, first2, UnaryTransform(&copies)); assert(copies == 0); + (void)std::transform(first, mid, mid, first2, BinaryTransform(&copies)); assert(copies == 0); + (void)std::unique(first, last, Equal(&copies)); assert(copies == 0); + (void)std::unique_copy(first, last, first2, Equal(&copies)); assert(copies == 0); + (void)std::upper_bound(first, last, value, Less(&copies)); assert(copies == 0); return true; } int main(int, char**) { - all_the_algorithms(); + all_the_algorithms(); + all_the_algorithms(); #if TEST_STD_VER > 17 - static_assert(all_the_algorithms()); + static_assert(all_the_algorithms()); + static_assert(all_the_algorithms()); #endif return 0;