@@ -103,6 +103,52 @@ namespace gfx {
103103
104104namespace detail {
105105
106+ // Equivalent to C++20 std::identity
107+ struct identity {
108+ #if GFX_TIMSORT_USE_STD_MOVE
109+ template <typename T>
110+ T&& operator ()(T&& value) const
111+ {
112+ return std::forward<T>(value);
113+ }
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
125+ };
126+
127+ // Merge a predicate and a projection function
128+ template <typename Compare, typename Projection>
129+ struct projection_compare {
130+ projection_compare (Compare comp, Projection proj) : compare(comp), projection(proj) {
131+ }
132+
133+ #if GFX_TIMSORT_USE_STD_MOVE
134+ template <typename T, typename U>
135+ bool operator ()(T &&lhs, U &&rhs) {
136+ return static_cast <bool >(compare (
137+ projection (std::forward<T>(lhs)),
138+ projection (std::forward<U>(rhs))
139+ ));
140+ }
141+ #else
142+ template <typename T, typename U>
143+ bool operator ()(T &lhs, U &rhs) {
144+ return static_cast <bool >(compare (projection (lhs), projection (rhs)));
145+ }
146+ #endif
147+
148+ Compare compare;
149+ Projection projection;
150+ };
151+
106152template <typename Iterator> struct run {
107153 typedef typename std::iterator_traits<Iterator>::difference_type diff_t ;
108154
@@ -669,12 +715,23 @@ template <typename RandomAccessIterator, typename Compare> class TimSort {
669715// Public interface implementation
670716// ---------------------------------------
671717
718+ /* *
719+ * Stably sorts a range with a comparison function and a projection function.
720+ */
721+ template <typename RandomAccessIterator, typename Compare, typename Projection>
722+ void timsort (RandomAccessIterator const first, RandomAccessIterator const last,
723+ Compare compare, Projection projection) {
724+ typedef detail::projection_compare<Compare, Projection> compare_t ;
725+ compare_t comp (compare, projection);
726+ detail::TimSort<RandomAccessIterator, compare_t >::sort (first, last, comp);
727+ }
728+
672729/* *
673730 * Same as std::stable_sort(first, last, compare).
674731 */
675732template <typename RandomAccessIterator, typename Compare>
676733void timsort (RandomAccessIterator const first, RandomAccessIterator const last, Compare compare) {
677- detail::TimSort<RandomAccessIterator, Compare>:: sort (first, last, compare);
734+ gfx::timsort (first, last, compare, detail::identity () );
678735}
679736
680737/* *
@@ -683,7 +740,7 @@ void timsort(RandomAccessIterator const first, RandomAccessIterator const last,
683740template <typename RandomAccessIterator>
684741void timsort (RandomAccessIterator const first, RandomAccessIterator const last) {
685742 typedef typename std::iterator_traits<RandomAccessIterator>::value_type value_type;
686- gfx::timsort (first, last, std::less<value_type>());
743+ gfx::timsort (first, last, std::less<value_type>(), detail::identity () );
687744}
688745
689746} // namespace gfx
0 commit comments