1212#include < catch.hpp>
1313#include < gfx/timsort.hpp>
1414
15+ namespace {
16+ // Helper types for the tests
17+
18+ // //////////////////////////////////////////////////////////
19+ // Timsort should work with types that are not
20+ // default-constructible
21+
22+ struct NonDefaultConstructible {
23+ int i;
24+
25+ NonDefaultConstructible (int i_) : i(i_) {
26+ }
27+
28+ friend bool operator <(NonDefaultConstructible const &x, NonDefaultConstructible const &y) {
29+ return x.i < y.i ;
30+ }
31+ };
32+
33+ // //////////////////////////////////////////////////////////
34+ // Tools to test the stability of the sort
35+
36+ enum id { foo, bar, baz };
37+
38+ typedef std::pair<int , id> pair_t ;
39+
40+ inline bool less_in_first (pair_t x, pair_t y) {
41+ return x.first < y.first ;
42+ }
43+
44+ // //////////////////////////////////////////////////////////
45+ // Timsort should work with iterators that don't have a
46+ // post-increment or post-decrement operation
47+
48+ template <typename Iterator>
49+ class NoPostIterator
50+ {
51+ public:
52+
53+ // //////////////////////////////////////////////////////////
54+ // Public types
55+
56+ typedef typename std::iterator_traits<Iterator>::iterator_category iterator_category;
57+ typedef Iterator iterator_type;
58+ typedef typename std::iterator_traits<Iterator>::value_type value_type;
59+ typedef typename std::iterator_traits<Iterator>::difference_type difference_type;
60+ typedef typename std::iterator_traits<Iterator>::pointer pointer;
61+ typedef typename std::iterator_traits<Iterator>::reference reference;
62+
63+ // //////////////////////////////////////////////////////////
64+ // Constructors
65+
66+ NoPostIterator () = default ;
67+
68+ explicit NoPostIterator (Iterator it) : _it(it) {
69+ }
70+
71+ // //////////////////////////////////////////////////////////
72+ // Members access
73+
74+ iterator_type base () const {
75+ return _it;
76+ }
77+
78+ // //////////////////////////////////////////////////////////
79+ // Element access
80+
81+ reference operator *() const {
82+ return *base ();
83+ }
84+
85+ pointer operator ->() const {
86+ return &(operator *());
87+ }
88+
89+ // //////////////////////////////////////////////////////////
90+ // Increment/decrement operators
91+
92+ NoPostIterator& operator ++() {
93+ ++_it;
94+ return *this ;
95+ }
96+
97+ NoPostIterator& operator --() {
98+ --_it;
99+ return *this ;
100+ }
101+
102+ NoPostIterator& operator +=(difference_type increment) {
103+ _it += increment;
104+ return *this ;
105+ }
106+
107+ NoPostIterator& operator -=(difference_type increment) {
108+ _it -= increment;
109+ return *this ;
110+ }
111+
112+ // //////////////////////////////////////////////////////////
113+ // Comparison operators
114+
115+ friend bool operator ==(NoPostIterator const & lhs, NoPostIterator const & rhs) {
116+ return lhs.base () == rhs.base ();
117+ }
118+
119+ friend bool operator !=(NoPostIterator const & lhs, NoPostIterator const & rhs) {
120+ return lhs.base () != rhs.base ();
121+ }
122+
123+ // //////////////////////////////////////////////////////////
124+ // Relational operators
125+
126+ friend bool operator <(NoPostIterator const & lhs, NoPostIterator const & rhs) {
127+ return lhs.base () < rhs.base ();
128+ }
129+
130+ friend bool operator <=(NoPostIterator const & lhs, NoPostIterator const & rhs) {
131+ return lhs.base () <= rhs.base ();
132+ }
133+
134+ friend bool operator >(NoPostIterator const & lhs, NoPostIterator const & rhs) {
135+ return lhs.base () > rhs.base ();
136+ }
137+
138+ friend bool operator >=(NoPostIterator const & lhs, NoPostIterator const & rhs) {
139+ return lhs.base () >= rhs.base ();
140+ }
141+
142+ // //////////////////////////////////////////////////////////
143+ // Arithmetic operators
144+
145+ friend NoPostIterator operator +(NoPostIterator it, difference_type size) {
146+ return it += size;
147+ }
148+
149+ friend NoPostIterator operator +(difference_type size, NoPostIterator it) {
150+ return it += size;
151+ }
152+
153+ friend NoPostIterator operator -(NoPostIterator it, difference_type size) {
154+ return it -= size;
155+ }
156+
157+ friend difference_type operator -(NoPostIterator const & lhs, NoPostIterator const & rhs) {
158+ return lhs.base () - rhs.base ();
159+ }
160+
161+ private:
162+
163+ Iterator _it;
164+ };
165+
166+ // //////////////////////////////////////////////////////////
167+ // Construction function
168+
169+ template <typename Iterator>
170+ NoPostIterator<Iterator> make_no_post_iterator (Iterator it) {
171+ return NoPostIterator<Iterator>(it);
172+ }
173+
174+ }
175+
15176TEST_CASE ( " simple0" ) {
16177 std::vector<int > a;
17178
@@ -358,17 +519,6 @@ TEST_CASE( "string_array" ) {
358519 CHECK (a[4 ] == " 9" );
359520}
360521
361- struct NonDefaultConstructible {
362- int i;
363-
364- NonDefaultConstructible (int i_) : i(i_) {
365- }
366-
367- friend bool operator <(NonDefaultConstructible const &x, NonDefaultConstructible const &y) {
368- return x.i < y.i ;
369- }
370- };
371-
372522TEST_CASE ( " non_default_constructible" ) {
373523 NonDefaultConstructible a[] = {7 , 1 , 5 , 3 , 9 };
374524
@@ -398,14 +548,6 @@ TEST_CASE( "default_compare_function" ) {
398548 }
399549}
400550
401- enum id { foo, bar, baz };
402-
403- typedef std::pair<int , id> pair_t ;
404-
405- inline bool less_in_first (pair_t x, pair_t y) {
406- return x.first < y.first ;
407- }
408-
409551TEST_CASE ( " stability" ) {
410552 std::vector<pair_t > a;
411553
@@ -446,13 +588,6 @@ TEST_CASE( "stability" ) {
446588 CHECK (a[11 ].second == baz);
447589}
448590
449- inline bool less_in_pair (const std::pair<int , int > &x, const std::pair<int , int > &y) {
450- if (x.first == y.first ) {
451- return x.second < y.second ;
452- }
453- return x.first < y.first ;
454- }
455-
456591TEST_CASE ( " issue2_duplication" ) {
457592 std::vector<std::pair<int , int > > a;
458593
@@ -465,8 +600,8 @@ TEST_CASE( "issue2_duplication" ) {
465600
466601 std::vector<std::pair<int , int > > expected (a);
467602
468- std::sort (expected.begin (), expected.end (), &less_in_pair );
469- gfx::timsort (a.begin (), a.end (), &less_in_pair );
603+ std::sort (expected.begin (), expected.end ());
604+ gfx::timsort (a.begin (), a.end ());
470605
471606#if 0
472607 for (std::size_t i = 0; i < a.size(); ++i) {
@@ -531,3 +666,11 @@ TEST_CASE( "projection" ) {
531666 CHECK (vec[i] == i - 40 );
532667 }
533668}
669+
670+ TEST_CASE ( " iterator without post-increment or post-decrement" ) {
671+ std::vector<int > a;
672+
673+ gfx::timsort (make_no_post_iterator (a.begin ()), make_no_post_iterator (a.end ()));
674+
675+ CHECK (a.size () == std::size_t (0 ));
676+ }
0 commit comments