Created
November 19, 2015 18:28
-
-
Save CaseyCarter/784067122e7d7de4b665 to your computer and use it in GitHub Desktop.
We can't require [i,s) equals [i,t) to imply s == t
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <experimental/ranges/algorithm> | |
| #include <cassert> | |
| using namespace std::experimental::ranges; | |
| struct S { | |
| int limit; | |
| #if FOO | |
| friend bool operator==(const S& a, const S& b) { return true; } | |
| friend bool operator!=(const S& a, const S& b) { return false; } | |
| #else | |
| friend bool operator==(const S& a, const S& b) { return a.limit == b.limit; } | |
| friend bool operator!=(const S& a, const S& b) { return !(a == b); } | |
| #endif | |
| template <InputIterator I> | |
| requires | |
| StrictTotallyOrdered<int, value_type_t<I>>() | |
| friend bool operator==(const I& i, const S& s) { return *i >= s.limit; } | |
| template <InputIterator I> | |
| requires | |
| StrictTotallyOrdered<int, value_type_t<I>>() | |
| friend bool operator==(const S& s, const I& i) { return i == s; } | |
| template <InputIterator I> | |
| requires | |
| StrictTotallyOrdered<int, value_type_t<I>>() | |
| friend bool operator!=(const I& i, const S& s) { return !(i == s); } | |
| template <InputIterator I> | |
| requires | |
| StrictTotallyOrdered<int, value_type_t<I>>() | |
| friend bool operator!=(const S& s, const I& i) { return !(i == s); } | |
| }; | |
| namespace std { namespace experimental { namespace ranges { | |
| template <InputIterator I> | |
| requires StrictTotallyOrdered<int, value_type_t<I>>() | |
| struct common_type<I, ::S> : meta::id<common_iterator<I, ::S>> {}; | |
| template <InputIterator I> | |
| requires StrictTotallyOrdered<int, value_type_t<I>>() | |
| struct common_type<::S, I> : meta::id<common_iterator<I, ::S>> {}; | |
| }}} | |
| static_assert(models::Sentinel<S,int*>); | |
| int main() { | |
| #if FOO | |
| int some_ints[] = {0,1,2,3,5,9,42}; | |
| auto s1 = S{5}; | |
| auto s2 = S{8}; | |
| // s1 and s2 are equal | |
| assert(s1 == s2); | |
| // So I can substitute them in equality preserving | |
| // expressions and get equal results | |
| assert(some_ints + 4 == s1); | |
| assert(some_ints + 4 == s2 && "Oops again."); | |
| #else | |
| int some_ints[] = {0,1,2,3,42}; | |
| auto r1 = ext::make_range(some_ints, S{5}); | |
| auto r2 = ext::make_range(some_ints, S{8}); | |
| // r1 and r2 have the same type | |
| static_assert(models::Same<decltype(r1),decltype(r2)>); | |
| // They are in fact RandomAccessRanges | |
| using R = decltype(r1); | |
| static_assert(models::RandomAccessRange<R>); | |
| // r1 and r2 are equal ranges | |
| assert(distance(r1) == distance(r2)); | |
| assert(equal(r1, r2)); | |
| // They have equal begin iterators | |
| assert(begin(r1) == begin(r2)); | |
| // Since int* satisfies ForwardIterator, its increment | |
| // operation is equality preserving. Therefore every | |
| // iterator in these two ranges must be equal, i.e., | |
| // they denote the same elements, up to/ and including | |
| // the past-the-end iterators | |
| auto i1 = begin(r1), i2 = begin(r2); | |
| while (true) { | |
| assert(i1 == i2); | |
| if (i1 == end(r1)) { | |
| assert(i2 == end(r2)); | |
| break; | |
| } | |
| ++i1, ++i2; | |
| } | |
| // Both i1 and i2 compare equal to both end(r1) and end(r2) | |
| assert(i1 == end(r1)); | |
| assert(i1 == end(r2)); | |
| assert(i2 == end(r1)); | |
| assert(i2 == end(r2)); | |
| // So by EqualityComparable, end(r1) == end(r2) | |
| assert(end(r1) == end(r2) && "Oops. They aren't equal."); | |
| #endif | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment