diff options
author | Derek Mauro <dmauro@google.com> | 2023-10-20 12:49:11 -0700 |
---|---|---|
committer | Copybara-Service <copybara-worker@google.com> | 2023-10-20 12:49:46 -0700 |
commit | b5fb0582b5bb46d622271a7db61e28ff19ae928c (patch) | |
tree | b58fdda8cebaa72c1d85d5009b9bab764672174b /absl/algorithm/algorithm.h | |
parent | 133360ca449bb2a44899e71f253856dca8443bdb (diff) |
Use STL algorithms available since C++14 to implement absl::equal and
absl::rotate.
Prior to C++14 these were either polyfills or fixes for bugs in
standard libraries.
PiperOrigin-RevId: 575295101
Change-Id: Ie01e77fedadc879c73203d71babd40c87a419af3
Diffstat (limited to 'absl/algorithm/algorithm.h')
-rw-r--r-- | absl/algorithm/algorithm.h | 111 |
1 files changed, 8 insertions, 103 deletions
diff --git a/absl/algorithm/algorithm.h b/absl/algorithm/algorithm.h index e9b47338..59aeed7d 100644 --- a/absl/algorithm/algorithm.h +++ b/absl/algorithm/algorithm.h @@ -31,92 +31,17 @@ namespace absl { ABSL_NAMESPACE_BEGIN -namespace algorithm_internal { - -// Performs comparisons with operator==, similar to C++14's `std::equal_to<>`. -struct EqualTo { - template <typename T, typename U> - bool operator()(const T& a, const U& b) const { - return a == b; - } -}; - -template <typename InputIter1, typename InputIter2, typename Pred> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred pred, std::input_iterator_tag, - std::input_iterator_tag) { - while (true) { - if (first1 == last1) return first2 == last2; - if (first2 == last2) return false; - if (!pred(*first1, *first2)) return false; - ++first1; - ++first2; - } -} - -template <typename InputIter1, typename InputIter2, typename Pred> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred, std::random_access_iterator_tag, - std::random_access_iterator_tag) { - return (last1 - first1 == last2 - first2) && - std::equal(first1, last1, first2, std::forward<Pred>(pred)); -} - -// When we are using our own internal predicate that just applies operator==, we -// forward to the non-predicate form of std::equal. This enables an optimization -// in libstdc++ that can result in std::memcmp being used for integer types. -template <typename InputIter1, typename InputIter2> -bool EqualImpl(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, algorithm_internal::EqualTo /* unused */, - std::random_access_iterator_tag, - std::random_access_iterator_tag) { - return (last1 - first1 == last2 - first2) && - std::equal(first1, last1, first2); -} - -template <typename It> -It RotateImpl(It first, It middle, It last, std::true_type) { - return std::rotate(first, middle, last); -} - -template <typename It> -It RotateImpl(It first, It middle, It last, std::false_type) { - std::rotate(first, middle, last); - return std::next(first, std::distance(middle, last)); -} - -} // namespace algorithm_internal - // equal() +// rotate() // -// Compares the equality of two ranges specified by pairs of iterators, using -// the given predicate, returning true iff for each corresponding iterator i1 -// and i2 in the first and second range respectively, pred(*i1, *i2) == true -// -// This comparison takes at most min(`last1` - `first1`, `last2` - `first2`) -// invocations of the predicate. Additionally, if InputIter1 and InputIter2 are -// both random-access iterators, and `last1` - `first1` != `last2` - `first2`, -// then the predicate is never invoked and the function returns false. +// Historical note: Abseil once provided implementations of these algorithms +// prior to their adoption in C++14. New code should prefer to use the std +// variants. // -// This is a C++11-compatible implementation of C++14 `std::equal`. See -// https://en.cppreference.com/w/cpp/algorithm/equal for more information. -template <typename InputIter1, typename InputIter2, typename Pred> -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2, Pred&& pred) { - return algorithm_internal::EqualImpl( - first1, last1, first2, last2, std::forward<Pred>(pred), - typename std::iterator_traits<InputIter1>::iterator_category{}, - typename std::iterator_traits<InputIter2>::iterator_category{}); -} - -// Overload of equal() that performs comparison of two ranges specified by pairs -// of iterators using operator==. -template <typename InputIter1, typename InputIter2> -bool equal(InputIter1 first1, InputIter1 last1, InputIter2 first2, - InputIter2 last2) { - return absl::equal(first1, last1, first2, last2, - algorithm_internal::EqualTo{}); -} +// See the documentation for the STL <algorithm> header for more information: +// https://en.cppreference.com/w/cpp/header/algorithm +using std::equal; +using std::rotate; // linear_search() // @@ -133,26 +58,6 @@ bool linear_search(InputIterator first, InputIterator last, return std::find(first, last, value) != last; } -// rotate() -// -// Performs a left rotation on a range of elements (`first`, `last`) such that -// `middle` is now the first element. `rotate()` returns an iterator pointing to -// the first element before rotation. This function is exactly the same as -// `std::rotate`, but fixes a bug in gcc -// <= 4.9 where `std::rotate` returns `void` instead of an iterator. -// -// The complexity of this algorithm is the same as that of `std::rotate`, but if -// `ForwardIterator` is not a random-access iterator, then `absl::rotate` -// performs an additional pass over the range to construct the return value. -template <typename ForwardIterator> -ForwardIterator rotate(ForwardIterator first, ForwardIterator middle, - ForwardIterator last) { - return algorithm_internal::RotateImpl( - first, middle, last, - std::is_same<decltype(std::rotate(first, middle, last)), - ForwardIterator>()); -} - ABSL_NAMESPACE_END } // namespace absl |