3333#include < algorithm>
3434#include < functional>
3535#include < iterator>
36+ #include < utility>
3637#include < vector>
3738
3839// Semantic versioning macros
5758# define GFX_TIMSORT_LOG (expr ) ((void )0 )
5859#endif
5960
60- // If GFX_TIMSORT_USE_STD_MOVE is not defined, try to define it as follows:
61- // - Check standard feature-testing macro
62- // - Check non-standard feature-testing macro
63- // - Check C++ standard (disable if < C++11)
64- // - Check compiler-specific versions known to support move semantics
65-
66- #ifndef GFX_TIMSORT_USE_STD_MOVE
67- # if defined(__cpp_rvalue_references)
68- # define GFX_TIMSORT_USE_STD_MOVE 1
69- # elif defined(__has_feature)
70- # if __has_feature(cxx_rvalue_references)
71- # define GFX_TIMSORT_USE_STD_MOVE 1
72- # else
73- # define GFX_TIMSORT_USE_STD_MOVE 0
74- # endif
75- # elif !(defined(__cplusplus) && __cplusplus >= 201103L)
76- # define GFX_TIMSORT_USE_STD_MOVE 0
77- # elif defined(_MSC_VER) && _MSC_VER >= 1700
78- # define GFX_TIMSORT_USE_STD_MOVE 1
79- # elif defined(__GNUC__) && (__GNUC__ >= 5 || (__GNUC__ >= 4 && __GNUC_MINOR__ >= 6))
80- # define GFX_TIMSORT_USE_STD_MOVE 1
81- # else
82- # define GFX_TIMSORT_USE_STD_MOVE 0
83- # endif
84- #endif
85-
86- #if GFX_TIMSORT_USE_STD_MOVE
87- #include < utility>
88- #define GFX_TIMSORT_MOVE (x ) std::move(x)
89- #define GFX_TIMSORT_MOVE_RANGE (in1, in2, out ) std::move((in1), (in2), (out));
90- #define GFX_TIMSORT_MOVE_BACKWARD (in1, in2, out ) std::move_backward((in1), (in2), (out));
91- #else
92- #define GFX_TIMSORT_MOVE (x ) (x)
93- #define GFX_TIMSORT_MOVE_RANGE (in1, in2, out ) std::copy((in1), (in2), (out));
94- #define GFX_TIMSORT_MOVE_BACKWARD (in1, in2, out ) std::copy_backward((in1), (in2), (out));
95- #endif
96-
9761
9862namespace gfx {
9963
@@ -105,23 +69,11 @@ namespace detail {
10569
10670// Equivalent to C++20 std::identity
10771struct identity {
108- #if GFX_TIMSORT_USE_STD_MOVE
10972 template <typename T>
110- T&& operator ()(T&& value) const
73+ constexpr T&& operator ()(T&& value) const noexcept
11174 {
11275 return std::forward<T>(value);
11376 }
114- #else
115- template <typename T>
116- T& operator ()(T& value) const {
117- return value;
118- }
119-
120- template <typename T>
121- T const & operator ()(T const & value) const {
122- return value;
123- }
124- #endif
12577};
12678
12779// Merge a predicate and a projection function
@@ -130,27 +82,20 @@ struct projection_compare {
13082 projection_compare (Compare comp, Projection proj) : compare(comp), projection(proj) {
13183 }
13284
133- #if GFX_TIMSORT_USE_STD_MOVE
13485 template <typename T, typename U>
13586 bool operator ()(T &&lhs, U &&rhs) {
136- # ifdef __cpp_lib_invoke
87+ #ifdef __cpp_lib_invoke
13788 return static_cast <bool >(std::invoke (compare,
13889 std::invoke (projection, std::forward<T>(lhs)),
13990 std::invoke (projection, std::forward<U>(rhs))
14091 ));
141- # else
92+ #else
14293 return static_cast <bool >(compare (
14394 projection (std::forward<T>(lhs)),
14495 projection (std::forward<U>(rhs))
14596 ));
146- # endif
147- }
148- #else
149- template <typename T, typename U>
150- bool operator ()(T &lhs, U &rhs) {
151- return static_cast <bool >(compare (projection (lhs), projection (rhs)));
152- }
15397#endif
98+ }
15499
155100 Compare compare;
156101 Projection projection;
@@ -190,13 +135,13 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
190135 }
191136 for (; start < hi; ++start) {
192137 GFX_TIMSORT_ASSERT (lo <= start);
193- value_t pivot = GFX_TIMSORT_MOVE (*start);
138+ value_t pivot = std::move (*start);
194139
195140 iter_t const pos = std::upper_bound (lo, start, pivot, compare);
196141 for (iter_t p = start; p > pos; --p) {
197- *p = GFX_TIMSORT_MOVE (*(p - 1 ));
142+ *p = std::move (*(p - 1 ));
198143 }
199- *pos = GFX_TIMSORT_MOVE (pivot);
144+ *pos = std::move (pivot);
200145 }
201146 }
202147
@@ -420,17 +365,17 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
420365
421366 static void rotateLeft (iter_t first, iter_t last)
422367 {
423- value_t tmp = GFX_TIMSORT_MOVE (*first);
424- iter_t last_1 = GFX_TIMSORT_MOVE_RANGE (first + 1 , last, first);
425- *last_1 = GFX_TIMSORT_MOVE (tmp);
368+ value_t tmp = std::move (*first);
369+ iter_t last_1 = std::move (first + 1 , last, first);
370+ *last_1 = std::move (tmp);
426371 }
427372
428373 static void rotateRight (iter_t first, iter_t last)
429374 {
430375 iter_t last_1 = last - 1 ;
431- value_t tmp = GFX_TIMSORT_MOVE (*last_1);
432- GFX_TIMSORT_MOVE_BACKWARD (first, last_1, last);
433- *first = GFX_TIMSORT_MOVE (tmp);
376+ value_t tmp = std::move (*last_1);
377+ std::move_backward (first, last_1, last);
378+ *first = std::move (tmp);
434379 }
435380
436381
@@ -452,7 +397,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
452397 iter_t cursor2 = base2;
453398 iter_t dest = base1;
454399
455- *dest = GFX_TIMSORT_MOVE (*cursor2);
400+ *dest = std::move (*cursor2);
456401 ++cursor2;
457402 ++dest;
458403 --len2;
@@ -469,7 +414,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
469414 GFX_TIMSORT_ASSERT (len2 > 0 );
470415
471416 if (compare (*cursor2, *cursor1)) {
472- *dest = GFX_TIMSORT_MOVE (*cursor2);
417+ *dest = std::move (*cursor2);
473418 ++cursor2;
474419 ++dest;
475420 ++count2;
@@ -478,7 +423,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
478423 goto epilogue;
479424 }
480425 } else {
481- *dest = GFX_TIMSORT_MOVE (*cursor1);
426+ *dest = std::move (*cursor1);
482427 ++cursor1;
483428 ++dest;
484429 ++count1;
@@ -495,7 +440,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
495440
496441 count1 = gallopRight (*cursor2, cursor1, len1, 0 , compare);
497442 if (count1 != 0 ) {
498- GFX_TIMSORT_MOVE_BACKWARD (cursor1, cursor1 + count1, dest + count1);
443+ std::move_backward (cursor1, cursor1 + count1, dest + count1);
499444 dest += count1;
500445 cursor1 += count1;
501446 len1 -= count1;
@@ -504,7 +449,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
504449 goto epilogue;
505450 }
506451 }
507- *dest = GFX_TIMSORT_MOVE (*cursor2);
452+ *dest = std::move (*cursor2);
508453 ++cursor2;
509454 ++dest;
510455 if (--len2 == 0 ) {
@@ -513,15 +458,15 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
513458
514459 count2 = gallopLeft (*cursor1, cursor2, len2, 0 , compare);
515460 if (count2 != 0 ) {
516- GFX_TIMSORT_MOVE_RANGE (cursor2, cursor2 + count2, dest);
461+ std::move (cursor2, cursor2 + count2, dest);
517462 dest += count2;
518463 cursor2 += count2;
519464 len2 -= count2;
520465 if (len2 == 0 ) {
521466 goto epilogue;
522467 }
523468 }
524- *dest = GFX_TIMSORT_MOVE (*cursor1);
469+ *dest = std::move (*cursor1);
525470 ++cursor1;
526471 ++dest;
527472 if (--len1 == 1 ) {
@@ -543,13 +488,13 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
543488
544489 if (len1 == 1 ) {
545490 GFX_TIMSORT_ASSERT (len2 > 0 );
546- GFX_TIMSORT_MOVE_RANGE (cursor2, cursor2 + len2, dest);
547- *(dest + len2) = GFX_TIMSORT_MOVE (*cursor1);
491+ std::move (cursor2, cursor2 + len2, dest);
492+ *(dest + len2) = std::move (*cursor1);
548493 } else {
549494 GFX_TIMSORT_ASSERT (len1 != 0 && " Comparison function violates its general contract" );
550495 GFX_TIMSORT_ASSERT (len2 == 0 );
551496 GFX_TIMSORT_ASSERT (len1 > 1 );
552- GFX_TIMSORT_MOVE_RANGE (cursor1, cursor1 + len1, dest);
497+ std::move (cursor1, cursor1 + len1, dest);
553498 }
554499 }
555500
@@ -571,7 +516,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
571516 tmp_iter_t cursor2 = tmp_.begin () + (len2 - 1 );
572517 iter_t dest = base2 + (len2 - 1 );
573518
574- *dest = GFX_TIMSORT_MOVE (*(--cursor1));
519+ *dest = std::move (*(--cursor1));
575520 --dest;
576521 --len1;
577522
@@ -593,7 +538,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
593538 GFX_TIMSORT_ASSERT (len2 > 1 );
594539
595540 if (compare (*cursor2, *cursor1)) {
596- *dest = GFX_TIMSORT_MOVE (*cursor1);
541+ *dest = std::move (*cursor1);
597542 --dest;
598543 ++count1;
599544 count2 = 0 ;
@@ -602,7 +547,7 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
602547 }
603548 --cursor1;
604549 } else {
605- *dest = GFX_TIMSORT_MOVE (*cursor2);
550+ *dest = std::move (*cursor2);
606551 --cursor2;
607552 --dest;
608553 ++count2;
@@ -624,13 +569,13 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
624569 dest -= count1;
625570 cursor1 -= count1;
626571 len1 -= count1;
627- GFX_TIMSORT_MOVE_BACKWARD (cursor1, cursor1 + count1, dest + (1 + count1));
572+ std::move_backward (cursor1, cursor1 + count1, dest + (1 + count1));
628573
629574 if (len1 == 0 ) {
630575 goto epilogue;
631576 }
632577 }
633- *dest = GFX_TIMSORT_MOVE (*cursor2);
578+ *dest = std::move (*cursor2);
634579 --cursor2;
635580 --dest;
636581 if (--len2 == 1 ) {
@@ -642,12 +587,12 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
642587 dest -= count2;
643588 cursor2 -= count2;
644589 len2 -= count2;
645- GFX_TIMSORT_MOVE_RANGE (cursor2 + 1 , cursor2 + (1 + count2), dest + 1 );
590+ std::move (cursor2 + 1 , cursor2 + (1 + count2), dest + 1 );
646591 if (len2 <= 1 ) {
647592 goto epilogue;
648593 }
649594 }
650- *dest = GFX_TIMSORT_MOVE (*(--cursor1));
595+ *dest = std::move (*(--cursor1));
651596 --dest;
652597 if (--len1 == 0 ) {
653598 goto epilogue;
@@ -669,23 +614,19 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
669614 if (len2 == 1 ) {
670615 GFX_TIMSORT_ASSERT (len1 > 0 );
671616 dest -= len1;
672- GFX_TIMSORT_MOVE_BACKWARD (cursor1 - len1, cursor1, dest + (1 + len1));
673- *dest = GFX_TIMSORT_MOVE (*cursor2);
617+ std::move_backward (cursor1 - len1, cursor1, dest + (1 + len1));
618+ *dest = std::move (*cursor2);
674619 } else {
675620 GFX_TIMSORT_ASSERT (len2 != 0 && " Comparison function violates its general contract" );
676621 GFX_TIMSORT_ASSERT (len1 == 0 );
677622 GFX_TIMSORT_ASSERT (len2 > 1 );
678- GFX_TIMSORT_MOVE_RANGE (tmp_.begin (), tmp_.begin () + len2, dest - (len2 - 1 ));
623+ std::move (tmp_.begin (), tmp_.begin () + len2, dest - (len2 - 1 ));
679624 }
680625 }
681626
682627 void copy_to_tmp (iter_t const begin, diff_t len) {
683- #if GFX_TIMSORT_USE_STD_MOVE
684628 tmp_.assign (std::make_move_iterator (begin),
685629 std::make_move_iterator (begin + len));
686- #else
687- tmp_.assign (begin, begin + len);
688- #endif
689630 }
690631
691632public:
@@ -773,9 +714,5 @@ void timsort(RandomAccessIterator const first, RandomAccessIterator const last)
773714#undef GFX_TIMSORT_ASSERT
774715#undef GFX_TIMSORT_ENABLE_LOG
775716#undef GFX_TIMSORT_LOG
776- #undef GFX_TIMSORT_MOVE
777- #undef GFX_TIMSORT_MOVE_RANGE
778- #undef GFX_TIMSORT_MOVE_BACKWARD
779- #undef GFX_TIMSORT_USE_STD_MOVE
780717
781718#endif // GFX_TIMSORT_HPP
0 commit comments