55
66module ;
77
8+ #include < bounded/assert.hpp>
89#include < operators/forward.hpp>
910
1011export module containers.algorithms.compare;
1112
1213import containers.begin_end;
1314import containers.iterator;
1415import containers.range;
16+ import containers.range_reference_t ;
1517import containers.sentinel_for;
1618import containers.size;
1719import containers.sized_range;
@@ -21,126 +23,84 @@ import std_module;
2123
2224namespace containers {
2325
24- export template <iterator InputIterator1, iterator InputIterator2>
25- constexpr auto lexicographical_compare_3way (InputIterator1 first1, sentinel_for<InputIterator1> auto const last1, InputIterator2 first2, sentinel_for<InputIterator2> auto const last2, auto cmp) -> decltype(cmp(*first1, *first2)) {
26- for (; first1 != last1 and first2 != last2; ++first1, ++first2) {
26+ template <typename Range1, typename Range2>
27+ using comparison_result = std::compare_three_way_result_t <
28+ containers::range_reference_t <Range1>,
29+ containers::range_reference_t <Range2>
30+ >;
31+
32+ export template <range Range1, range Range2, typename Compare = std::compare_three_way>
33+ constexpr auto lexicographical_compare_assume_same_size (
34+ Range1 && range1,
35+ Range2 && range2,
36+ Compare cmp = std::compare_three_way()
37+ ) -> comparison_result<Range1, Range2> {
38+ if constexpr (sized_range<Range1> and sized_range<Range2>) {
39+ BOUNDED_ASSERT (::containers::size (range1) == ::containers::size (range2));
40+ }
41+ auto const last1 = containers::end (OPERATORS_FORWARD (range1));
42+ auto first1 = containers::begin (OPERATORS_FORWARD (range1));
43+ auto first2 = containers::begin (OPERATORS_FORWARD (range2));
44+ for (; first1 != last1; ++first1, ++first2) {
2745 if (auto const result = cmp (*first1, *first2); result != 0 ) {
2846 return result;
2947 }
3048 }
31- return
32- (first1 != last1) ? std::strong_ordering::greater :
33- (first2 != last2) ? std::strong_ordering::less :
34- std::strong_ordering::equal;
35- }
36-
37- export constexpr auto lexicographical_compare_3way (range auto && range1, range auto && range2, auto cmp) {
38- return ::containers::lexicographical_compare_3way (
39- containers::begin (OPERATORS_FORWARD (range1)),
40- containers::end (OPERATORS_FORWARD (range1)),
41- containers::begin (OPERATORS_FORWARD (range2)),
42- containers::end (OPERATORS_FORWARD (range2)),
43- std::move (cmp)
44- );
45- }
46-
47-
48- export template <iterator InputIterator1, iterator InputIterator2>
49- constexpr auto lexicographical_compare_3way (InputIterator1 first1, sentinel_for<InputIterator1> auto last1, InputIterator2 first2, sentinel_for<InputIterator2> auto last2) {
50- return ::containers::lexicographical_compare_3way (
51- std::move (first1),
52- std::move (last1),
53- std::move (first2),
54- std::move (last2),
55- std::compare_three_way ()
56- );
57- }
58-
59- export constexpr auto lexicographical_compare_3way (range auto && range1, range auto && range2) {
60- return ::containers::lexicographical_compare_3way (
61- OPERATORS_FORWARD (range1),
62- OPERATORS_FORWARD (range2),
63- std::compare_three_way ()
64- );
49+ return std::strong_ordering::equal;
6550}
6651
67-
68- export template <iterator InputIterator1, iterator InputIterator2>
69- constexpr auto lexicographical_compare_3way (InputIterator1 first1, sentinel_for<InputIterator1> auto const last1, InputIterator2 first2, auto cmp) requires(!sentinel_for<decltype (cmp), InputIterator2>) {
70- for (; first1 != last1; ++first1, ++first2) {
52+ export template <range Range1, range Range2, typename Compare = std::compare_three_way>
53+ constexpr auto lexicographical_compare (
54+ Range1 && range1,
55+ Range2 && range2,
56+ Compare cmp = std::compare_three_way()
57+ ) -> comparison_result<Range1, Range2> {
58+ auto const last1 = containers::end (OPERATORS_FORWARD (range1));
59+ auto first1 = containers::begin (OPERATORS_FORWARD (range1));
60+ auto const last2 = containers::end (OPERATORS_FORWARD (range2));
61+ auto first2 = containers::begin (OPERATORS_FORWARD (range2));
62+ for (; first1 != last1 and first2 != last2; ++first1, ++first2) {
7163 if (auto const result = cmp (*first1, *first2); result != 0 ) {
7264 return result;
7365 }
7466 }
75- return std::strong_ordering::equal;
76- }
77-
78- export template <iterator InputIterator1>
79- constexpr auto lexicographical_compare_3way (InputIterator1 first1, sentinel_for<InputIterator1> auto last1, iterator auto first2) {
80- return ::containers::lexicographical_compare_3way (
81- std::move (first1),
82- std::move (last1),
83- std::move (first2),
84- std::compare_three_way ()
85- );
67+ return
68+ (first1 != last1) ? std::strong_ordering::greater :
69+ (first2 != last2) ? std::strong_ordering::less :
70+ std::strong_ordering::equal;
8671}
8772
88-
89-
9073// Shorter ranges compare less than longer ranges. Ranges of the same length
9174// compare lexicographically.
92- export constexpr auto shortlex_compare (sized_range auto && range1, sized_range auto && range2, auto cmp) {
75+ export template <sized_range Range1, sized_range Range2, typename Compare = std::compare_three_way>
76+ constexpr auto shortlex_compare (
77+ Range1 && range1,
78+ Range2 && range2,
79+ Compare cmp = std::compare_three_way()
80+ ) -> comparison_result<Range1, Range2> {
9381 if (auto const result = ::containers::size (range1) <=> ::containers::size (range2); result != 0 ) {
9482 return result;
9583 }
96- return ::containers::lexicographical_compare_3way (
97- ::containers::begin (OPERATORS_FORWARD(range1)),
98- ::containers::end(OPERATORS_FORWARD(range1)),
99- ::containers::begin(OPERATORS_FORWARD(range2)),
100- std::move(cmp)
101- );
102- }
103-
104- export constexpr auto shortlex_compare (sized_range auto && range1, sized_range auto && range2) {
105- return ::containers::shortlex_compare (
84+ return ::containers::lexicographical_compare_assume_same_size (
10685 OPERATORS_FORWARD (range1),
10786 OPERATORS_FORWARD (range2),
108- std::compare_three_way ( )
87+ std::move (cmp )
10988 );
11089}
11190
11291
113-
114-
115-
116-
117-
118-
119-
120- export template <iterator InputIterator1, iterator InputIterator2>
121- constexpr auto equal (InputIterator1 first1, sentinel_for<InputIterator1> auto const last1, InputIterator2 first2, sentinel_for<InputIterator2> auto const last2, auto cmp) {
122- for (; first1 != last1 and first2 != last2; ++first1, ++first2) {
123- if (!cmp (*first1, *first2)) {
124- return false ;
125- }
92+ export template <range Range1, range Range2, typename Compare = std::equal_to<>>
93+ constexpr auto equal_assume_same_size (
94+ Range1 && range1,
95+ Range2 && range2,
96+ Compare cmp = std::equal_to()
97+ ) -> bool {
98+ if constexpr (sized_range<Range1> and sized_range<Range2>) {
99+ BOUNDED_ASSERT (::containers::size (range1) == ::containers::size (range2));
126100 }
127- return first1 == last1 and first2 == last2;
128- }
129-
130-
131- export template <iterator InputIterator1, iterator InputIterator2>
132- constexpr auto equal (InputIterator1 first1, sentinel_for<InputIterator1> auto last1, InputIterator2 first2, sentinel_for<InputIterator2> auto last2) {
133- return ::containers::equal (
134- std::move (first1),
135- std::move (last1),
136- std::move (first2),
137- std::move (last2),
138- bounded::equal_to ()
139- );
140- }
141-
142- export template <iterator InputIterator1, iterator InputIterator2>
143- constexpr auto equal (InputIterator1 first1, sentinel_for<InputIterator1> auto const last1, InputIterator2 first2, auto cmp) requires(!sentinel_for<decltype (cmp), InputIterator2>) {
101+ auto const last1 = containers::end (OPERATORS_FORWARD (range1));
102+ auto first1 = containers::begin (OPERATORS_FORWARD (range1));
103+ auto first2 = containers::begin (OPERATORS_FORWARD (range2));
144104 for (; first1 != last1; ++first1, ++first2) {
145105 if (!cmp (*first1, *first2)) {
146106 return false ;
@@ -149,45 +109,33 @@ constexpr auto equal(InputIterator1 first1, sentinel_for<InputIterator1> auto co
149109 return true ;
150110}
151111
152- export template <iterator InputIterator1, iterator InputIterator2>
153- constexpr auto equal (InputIterator1 first1, sentinel_for<InputIterator1> auto last1, InputIterator2 first2) {
154- return ::containers::equal (
155- std::move (first1),
156- std::move (last1),
157- std::move (first2),
158- bounded::equal_to ()
159- );
160- }
161112
162- export template <range Range1, range Range2>
163- constexpr auto equal (Range1 && range1, Range2 && range2, auto cmp) {
113+ export template <range Range1, range Range2, typename Compare = std::equal_to<>>
114+ constexpr auto equal (
115+ Range1 && range1,
116+ Range2 && range2,
117+ Compare cmp = std::equal_to()
118+ ) -> bool {
164119 if constexpr (sized_range<Range1> and sized_range<Range2>) {
165120 return
166121 ::containers::size (range1) == ::containers::size(range2) and
167- ::containers::equal(
168- containers::begin (OPERATORS_FORWARD(range1)),
169- containers::end(OPERATORS_FORWARD(range1)),
170- containers::begin(OPERATORS_FORWARD(range2)),
122+ ::containers::equal_assume_same_size(
123+ OPERATORS_FORWARD (range1),
124+ OPERATORS_FORWARD(range2),
171125 std::move(cmp)
172126 );
173127 } else {
174- return ::containers::equal (
175- containers::begin (OPERATORS_FORWARD (range1)),
176- containers::end (OPERATORS_FORWARD (range1)),
177- containers::begin (OPERATORS_FORWARD (range2)),
178- containers::end (OPERATORS_FORWARD (range2)),
179- std::move (cmp)
180- );
128+ auto const last1 = containers::end (OPERATORS_FORWARD (range1));
129+ auto first1 = containers::begin (OPERATORS_FORWARD (range1));
130+ auto const last2 = containers::end (OPERATORS_FORWARD (range2));
131+ auto first2 = containers::begin (OPERATORS_FORWARD (range2));
132+ for (; first1 != last1 and first2 != last2; ++first1, ++first2) {
133+ if (!cmp (*first1, *first2)) {
134+ return false ;
135+ }
136+ }
137+ return first1 == last1 and first2 == last2;
181138 }
182139}
183140
184- export template <range Range1, range Range2>
185- constexpr auto equal (Range1 && range1, Range2 && range2) {
186- return ::containers::equal (
187- OPERATORS_FORWARD (range1),
188- OPERATORS_FORWARD (range2),
189- bounded::equal_to ()
190- );
191- }
192-
193141} // namespace containers
0 commit comments