Skip to content

Commit 476d5ab

Browse files
committed
if constexpr (#66)
1 parent 13e1939 commit 476d5ab

File tree

9 files changed

+78
-151
lines changed

9 files changed

+78
-151
lines changed

include/cpp-sort/detail/adaptive_quickselect.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2022 Morwenn
2+
* Copyright (c) 2021-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55

@@ -88,7 +88,7 @@ namespace detail
8888
std::swap(c, d);
8989
}
9090

91-
if (LeanRight) {
91+
if constexpr (LeanRight) {
9292
if (comp(proj(r[c]), proj(r[a]))) {
9393
CPPSORT_ASSERT(comp(proj(r[c]), proj(r[a])) && not comp(proj(r[d]), proj(r[c]))); // so r[c]) is out
9494
return median_index(r, a, b, d, std::move(compare), std::move(projection));

include/cpp-sort/detail/drop_merge_sort.h

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017-2022 Morwenn
2+
* Copyright (c) 2017-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55

@@ -74,12 +74,14 @@ namespace detail
7474
do {
7575
if (begin != write && comp(proj(*read), proj(*std::prev(write)))) {
7676

77-
if (double_comparison && num_dropped_in_row == 0 && write != std::next(begin) &&
78-
not comp(proj(*read), proj(*std::prev(write, 2)))) {
79-
dropped.push_back(iter_move(std::prev(write)));
80-
*std::prev(write) = iter_move(read);
81-
++read;
82-
continue;
77+
if constexpr (double_comparison) {
78+
if (num_dropped_in_row == 0 && write != std::next(begin) &&
79+
not comp(proj(*read), proj(*std::prev(write, 2)))) {
80+
dropped.push_back(iter_move(std::prev(write)));
81+
*std::prev(write) = iter_move(read);
82+
++read;
83+
continue;
84+
}
8385
}
8486

8587
if (num_dropped_in_row < recency) {
@@ -89,7 +91,7 @@ namespace detail
8991
} else {
9092
for (difference_type i = 0 ; i < num_dropped_in_row ; ++i) {
9193
--read;
92-
if (not std::is_trivially_copyable<rvalue_type>::value) {
94+
if constexpr (not std::is_trivially_copyable<rvalue_type>::value) {
9395
// If the value is trivially copyable, then it shouldn't have
9496
// been modified by the call to iter_move, and the original
9597
// value is still fully where it should be
@@ -104,7 +106,7 @@ namespace detail
104106
num_dropped_in_row = 0;
105107
}
106108
} else {
107-
if (std::is_trivially_copyable<rvalue_type>::value) {
109+
if constexpr (std::is_trivially_copyable<rvalue_type>::value) {
108110
// If the type is trivially copyable, the potential self-move
109111
// should not trigger any issue
110112
*write = iter_move(read);

include/cpp-sort/detail/longest_non_descending_subsequence.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021-2022 Morwenn
2+
* Copyright (c) 2021-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55
#ifndef CPPSORT_DETAIL_LONGEST_NON_DESCENDING_SUBSEQUENCE_H_
@@ -52,7 +52,7 @@ namespace detail
5252
// we can compute it as-we-go when it is not known in order to avoid
5353
// making two passes over the sequence - when the sequence is made
5454
// of random-access iterators, we only compute it once
55-
if (RecomputeSize && is_random_access) {
55+
if constexpr (RecomputeSize && is_random_access) {
5656
size = std::distance(first, last);
5757
}
5858

@@ -77,7 +77,7 @@ namespace detail
7777
}
7878
++first;
7979

80-
if (RecomputeSize && not is_random_access) {
80+
if constexpr (RecomputeSize && not is_random_access) {
8181
// Compute the size as-we-go if iterators are not random-access
8282
++size;
8383
}

include/cpp-sort/detail/move.h

Lines changed: 30 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -25,88 +25,57 @@ namespace detail
2525

2626
template<typename InputIterator, typename OutputIterator>
2727
auto move(InputIterator first, InputIterator last, OutputIterator result)
28-
-> detail::enable_if_t<
29-
not cppsort::detail::has_iter_move_v<InputIterator>,
30-
OutputIterator
31-
>
28+
-> OutputIterator
3229
{
33-
return std::move(first, last, result);
34-
}
35-
36-
template<typename InputIterator, typename OutputIterator>
37-
auto move(InputIterator first, InputIterator last, OutputIterator result)
38-
-> detail::enable_if_t<
39-
cppsort::detail::has_iter_move_v<InputIterator>,
40-
OutputIterator
41-
>
42-
{
43-
for (; first != last; ++first, (void) ++result) {
44-
using utility::iter_move;
45-
*result = iter_move(first);
30+
if constexpr (cppsort::detail::has_iter_move_v<InputIterator>) {
31+
for (; first != last; ++first, (void) ++result) {
32+
using utility::iter_move;
33+
*result = iter_move(first);
34+
}
35+
return result;
36+
} else {
37+
return std::move(first, last, result);
4638
}
47-
return result;
4839
}
4940

5041
////////////////////////////////////////////////////////////
5142
// move_backward
5243

5344
template<typename InputIterator, typename OutputIterator>
5445
auto move_backward(InputIterator first, InputIterator last, OutputIterator result)
55-
-> detail::enable_if_t<
56-
not cppsort::detail::has_iter_move_v<InputIterator>,
57-
OutputIterator
58-
>
59-
{
60-
return std::move_backward(first, last, result);
61-
}
62-
63-
template<typename InputIterator, typename OutputIterator>
64-
auto move_backward(InputIterator first, InputIterator last, OutputIterator result)
65-
-> detail::enable_if_t<
66-
cppsort::detail::has_iter_move_v<InputIterator>,
67-
OutputIterator
68-
>
46+
-> OutputIterator
6947
{
70-
while (first != last) {
71-
using utility::iter_move;
72-
*--result = iter_move(--last);
48+
if constexpr (cppsort::detail::has_iter_move_v<InputIterator>) {
49+
while (first != last) {
50+
using utility::iter_move;
51+
*--result = iter_move(--last);
52+
}
53+
return result;
54+
} else {
55+
return std::move_backward(first, last, result);
7356
}
74-
return result;
7557
}
7658

7759
////////////////////////////////////////////////////////////
7860
// uninitialized_move
7961

80-
template<typename InputIterator, typename T>
81-
auto uninitialized_move_impl(std::true_type, InputIterator first, InputIterator last,
82-
T* result, destruct_n<T>&)
83-
-> T*
84-
{
85-
return detail::move(first, last, result);
86-
}
87-
88-
template<typename InputIterator, typename T>
89-
auto uninitialized_move_impl(std::false_type, InputIterator first, InputIterator last,
90-
T* result, destruct_n<T>& destroyer)
91-
-> T*
92-
{
93-
for (; first != last; ++first, (void) ++result, ++destroyer) {
94-
using utility::iter_move;
95-
::new(static_cast<void*>(result)) T(iter_move(first));
96-
}
97-
return result;
98-
}
99-
10062
template<typename InputIterator, typename T>
10163
auto uninitialized_move(InputIterator first, InputIterator last, T* result, destruct_n<T>& destroyer)
10264
-> T*
10365
{
104-
using truth_type = std::bool_constant<
66+
constexpr bool is_trivial_enough =
10567
std::is_trivial<value_type_t<InputIterator>>::value &&
106-
std::is_trivial<T>::value
107-
>;
108-
return uninitialized_move_impl(truth_type{}, std::move(first), std::move(last),
109-
std::move(result), destroyer);
68+
std::is_trivial<T>::value;
69+
70+
if (is_trivial_enough) {
71+
return detail::move(first, last, result);
72+
} else {
73+
for (; first != last; ++first, (void) ++result, ++destroyer) {
74+
using utility::iter_move;
75+
::new(static_cast<void*>(result)) T(iter_move(first));
76+
}
77+
return result;
78+
}
11079
}
11180
}}
11281

include/cpp-sort/detail/reverse.h

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2022 Morwenn
2+
* Copyright (c) 2016-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55

@@ -23,7 +23,6 @@
2323
#include <cpp-sort/utility/iter_move.h>
2424
#include "iterator_traits.h"
2525
#include "move.h"
26-
#include "type_traits.h"
2726

2827
namespace cppsort
2928
{
@@ -43,35 +42,23 @@ namespace detail
4342
}
4443
}
4544

46-
#if defined(_USE_STD_VECTOR_ALGORITHMS) && _USE_STD_VECTOR_ALGORITHMS
4745
template<typename RandomAccessIterator>
4846
auto reverse_impl(RandomAccessIterator first, RandomAccessIterator last,
4947
std::random_access_iterator_tag)
50-
-> detail::enable_if_t<
51-
not detail::has_iter_move_v<RandomAccessIterator>,
52-
void
53-
>
48+
-> void
5449
{
55-
std::reverse(first, last);
56-
}
57-
#endif
58-
59-
template<typename RandomAccessIterator>
60-
auto reverse_impl(RandomAccessIterator first, RandomAccessIterator last,
61-
std::random_access_iterator_tag)
6250
#if defined(_USE_STD_VECTOR_ALGORITHMS) && _USE_STD_VECTOR_ALGORITHMS
63-
-> detail::enable_if_t<
64-
detail::has_iter_move_v<RandomAccessIterator>,
65-
void
66-
>
67-
#else
68-
-> void
51+
if constexpr (not detail::has_iter_move_v<RandomAccessIterator>) {
52+
std::reverse(first, last);
53+
}
54+
else
6955
#endif
70-
{
71-
if (first != last) {
72-
for (; first < --last ; ++first) {
73-
using utility::iter_swap;
74-
iter_swap(first, last);
56+
{
57+
if (first != last) {
58+
for (; first < --last ; ++first) {
59+
using utility::iter_swap;
60+
iter_swap(first, last);
61+
}
7562
}
7663
}
7764
}

include/cpp-sort/detail/rotate.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ namespace detail
134134
-> ForwardIterator
135135
{
136136
using value_type = value_type_t<ForwardIterator>;
137-
if (std::is_trivially_move_assignable<value_type>::value)
137+
if constexpr (std::is_trivially_move_assignable<value_type>::value)
138138
{
139139
if (std::next(first) == middle)
140140
return rotate_left(first, last);
@@ -148,7 +148,7 @@ namespace detail
148148
-> BidirectionalIterator
149149
{
150150
using value_type = value_type_t<BidirectionalIterator>;
151-
if (std::is_trivially_move_assignable<value_type>::value)
151+
if constexpr (std::is_trivially_move_assignable<value_type>::value)
152152
{
153153
if (std::next(first) == middle)
154154
return rotate_left(first, last);
@@ -164,7 +164,7 @@ namespace detail
164164
-> RandomAccessIterator
165165
{
166166
using value_type = value_type_t<RandomAccessIterator>;
167-
if (std::is_trivially_move_assignable<value_type>::value)
167+
if constexpr (std::is_trivially_move_assignable<value_type>::value)
168168
{
169169
if (std::next(first) == middle)
170170
return rotate_left(first, last);

include/cpp-sort/detail/swap_ranges.h

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016-2022 Morwenn
2+
* Copyright (c) 2016-2025 Morwenn
33
* SPDX-License-Identifier: MIT
44
*/
55
#ifndef CPPSORT_DETAIL_SWAP_RANGES_H_
@@ -9,14 +9,11 @@
99
// Headers
1010
////////////////////////////////////////////////////////////
1111
#include <algorithm>
12-
#include <cstddef>
1312
#include <iterator>
14-
#include <type_traits>
1513
#include <cpp-sort/utility/iter_move.h>
1614
#include "config.h"
1715
#include "iterator_traits.h"
1816
#include "move.h"
19-
#include "type_traits.h"
2017

2118
namespace cppsort
2219
{
@@ -73,15 +70,11 @@ namespace detail
7370
return swap_ranges_overlap(first1, last1, first2);
7471
}
7572

76-
#if defined(_USE_STD_VECTOR_ALGORITHMS) && _USE_STD_VECTOR_ALGORITHMS
7773
template<typename RandomAccessIterator>
7874
auto swap_ranges_inner_impl(std::random_access_iterator_tag,
7975
RandomAccessIterator first1, RandomAccessIterator last1,
8076
RandomAccessIterator first2)
81-
-> detail::enable_if_t<
82-
not detail::has_iter_move_v<RandomAccessIterator>,
83-
RandomAccessIterator
84-
>
77+
-> RandomAccessIterator
8578
{
8679
CPPSORT_ASSERT(first1 <= last1);
8780

@@ -90,30 +83,11 @@ namespace detail
9083
CPPSORT_ASSERT(not (first2 >= first1 && first2 < last1));
9184
CPPSORT_ASSERT(not (last2 > first1 && last2 <= last1));
9285

93-
return std::_Swap_ranges_unchecked(first1, last1, first2);
94-
}
95-
#endif
96-
97-
template<typename RandomAccessIterator>
98-
auto swap_ranges_inner_impl(std::random_access_iterator_tag,
99-
RandomAccessIterator first1, RandomAccessIterator last1,
100-
RandomAccessIterator first2)
10186
#if defined(_USE_STD_VECTOR_ALGORITHMS) && _USE_STD_VECTOR_ALGORITHMS
102-
-> detail::enable_if_t<
103-
detail::has_iter_move_v<RandomAccessIterator>,
104-
RandomAccessIterator
105-
>
106-
#else
107-
-> RandomAccessIterator
87+
if constexpr (not detail::has_iter_move_v<RandomAccessIterator>) {
88+
return std::_Swap_ranges_unchecked(first1, last1, first2);
89+
}
10890
#endif
109-
{
110-
CPPSORT_ASSERT(first1 <= last1);
111-
112-
auto last2 = first2 + (last1 - first1);
113-
(void)last2;
114-
CPPSORT_ASSERT(not (first2 >= first1 && first2 < last1));
115-
CPPSORT_ASSERT(not (last2 > first1 && last2 <= last1));
116-
11791
return detail::swap_ranges_overlap(first1, last1, first2);
11892
}
11993

0 commit comments

Comments
 (0)