std:: equal
Defined in header
<algorithm>
|
||
template
<
class
InputIt1,
class
InputIt2
>
bool
equal
(
InputIt1 first1, InputIt1 last1,
|
(1) | (constexpr since C++20) |
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2
>
bool
equal
(
ExecutionPolicy
&&
policy,
|
(2) | (since C++17) |
template
<
class
InputIt1,
class
InputIt2,
class
BinaryPred
>
bool
equal
(
InputIt1 first1, InputIt1 last1,
|
(3) | (constexpr since C++20) |
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2,
class
BinaryPred
>
|
(4) | (since C++17) |
template
<
class
InputIt1,
class
InputIt2
>
bool
equal
(
InputIt1 first1, InputIt1 last1,
|
(5) |
(since C++14)
(constexpr since C++20) |
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2
>
bool
equal
(
ExecutionPolicy
&&
policy,
|
(6) | (since C++17) |
template
<
class
InputIt1,
class
InputIt2,
class
BinaryPred
>
bool
equal
(
InputIt1 first1, InputIt1 last1,
|
(7) |
(since C++14)
(constexpr since C++20) |
template
<
class
ExecutionPolicy,
class
ForwardIt1,
class
ForwardIt2,
class
BinaryPred
>
|
(8) | (since C++17) |
Checks whether
[
first1
,
last1
)
and a range starting from
first2
are equal:
- For overloads (1-4) , the second range has std:: distance ( first1, last1 ) elements.
-
For overloads
(5-8)
, the second range is
[
first2,
last2)
.
std:: is_execution_policy_v < std:: decay_t < ExecutionPolicy >> is true . |
(until C++20) |
std:: is_execution_policy_v < std:: remove_cvref_t < ExecutionPolicy >> is true . |
(since C++20) |
Parameters
first1, last1 | - | the first range of the elements to compare |
first2, last2 | - | the second range of the elements to compare |
policy | - | the execution policy to use. See execution policy for details. |
p | - |
binary predicate which returns
true
if the elements should be treated as equal.
The signature of the predicate function should be equivalent to the following: bool pred ( const Type1 & a, const Type2 & b ) ;
While the signature does not need to have
const
&
, the function must not modify the objects passed to it and must be able to accept all values of type (possibly const)
|
Type requirements | ||
-
InputIt1, InputIt2
must meet the requirements of
LegacyInputIterator
.
|
||
-
ForwardIt1, ForwardIt2
must meet the requirements of
LegacyForwardIterator
.
|
||
-
BinaryPred
must meet the requirements of
BinaryPredicate
.
|
Return value
Complexity
Given N 1 as std:: distance ( first1, last1 ) and N 2 as std:: distance ( first2, last2 ) :
InputIt1
and
InputIt2
are both
LegacyRandomAccessIterator
, and
last1
-
first1
!
=
last2
-
first2
is
true
, no comparison will be made.
Exceptions
The overloads with a template parameter named
ExecutionPolicy
report errors as follows:
-
If execution of a function invoked as part of the algorithm throws an exception and
ExecutionPolicy
is one of the standard policies , std::terminate is called. For any otherExecutionPolicy
, the behavior is implementation-defined. - If the algorithm fails to allocate memory, std::bad_alloc is thrown.
Possible implementation
equal (1) |
---|
template<class InputIt1, class InputIt2> constexpr //< since C++20 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2) { for (; first1 != last1; ++first1, ++first2) if (!(*first1 == *first2)) return false; return true; } |
equal (3) |
template<class InputIt1, class InputIt2, class BinaryPred> constexpr //< since C++20 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPred p) { for (; first1 != last1; ++first1, ++first2) if (!p(*first1, *first2)) return false; return true; } |
equal (5) |
namespace detail { // random-access iterator implementation (allows quick range size detection) template<class RandomIt1, class RandomIt2> constexpr //< since C++20 bool equal(RandomIt1 first1, RandomIt1 last1, RandomIt2 first2, RandomIt2 last2, std::random_access_iterator_tag, std::random_access_iterator_tag) { if (last1 - first1 != last2 - first2) return false; for (; first1 != last1; ++first1, ++first2) if (!(*first1 == *first2)) return false; return true; } // input iterator implementation (needs to manually compare with “last2”) template<class InputIt1, class InputIt2> constexpr //< since C++20 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, std::input_iterator_tag, std::input_iterator_tag) { for (; first1 != last1 && first2 != last2; ++first1, ++first2) if (!(*first1 == *first2)) return false; return first1 == last1 && first2 == last2; } } template<class InputIt1, class InputIt2> constexpr //< since C++20 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { details::equal(first1, last1, first2, last2, typename std::iterator_traits<InputIt1>::iterator_category(), typename std::iterator_traits<InputIt2>::iterator_category()); } |
equal (7) |
namespace detail { // random-access iterator implementation (allows quick range size detection) template<class RandomIt1, class RandomIt2, class BinaryPred> constexpr //< since C++20 bool equal(RandomIt1 first1, RandomIt1 last1, RandomIt2 first2, RandomIt2 last2, BinaryPred p, std::random_access_iterator_tag, std::random_access_iterator_tag) { if (last1 - first1 != last2 - first2) return false; for (; first1 != last1; ++first1, ++first2) if (!p(*first1, *first2)) return false; return true; } // input iterator implementation (needs to manually compare with “last2”) template<class InputIt1, class InputIt2, class BinaryPred> constexpr //< since C++20 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPred p, std::input_iterator_tag, std::input_iterator_tag) { for (; first1 != last1 && first2 != last2; ++first1, ++first2) if (!p(*first1, *first2)) return false; return first1 == last1 && first2 == last2; } } template<class InputIt1, class InputIt2, class BinaryPred> constexpr //< since C++20 bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, BinaryPred p) { details::equal(first1, last1, first2, last2, p, typename std::iterator_traits<InputIt1>::iterator_category(), typename std::iterator_traits<InputIt2>::iterator_category()); } |
Notes
std::equal
should not be used to compare the ranges formed by the iterators from
std::unordered_set
,
std::unordered_multiset
,
std::unordered_map
, or
std::unordered_multimap
because the order in which the elements are stored in those containers may be different even if the two containers store the same elements.
When comparing entire containers or string views (since C++17) for equality, operator == for the corresponding type are usually preferred.
Sequential
std::equal
is not guaranteed to be short-circuit. E.g. if the first pair elements of both ranges do not compare equal, the rest of elements may also be compared. Non-short-circuit comparison may happen when the ranges are compared with
std::memcmp
or implementation-specific vectorized algorithms.
Example
The following code uses
std::equal
to test if a string is a palindrome.
#include <algorithm> #include <iomanip> #include <iostream> #include <string_view> constexpr bool is_palindrome(const std::string_view& s) { return std::equal(s.cbegin(), s.cbegin() + s.size() / 2, s.crbegin()); } void test(const std::string_view& s) { std::cout << std::quoted(s) << (is_palindrome(s) ? " is" : " is not") << " a palindrome\n"; } int main() { test("radar"); test("hello"); }
Output:
"radar" is a palindrome "hello" is not a palindrome
See also
(C++11)
|
finds the first element satisfying specific criteria
(function template) |
returns
true
if one range is lexicographically less than another
(function template) |
|
finds the first position where two ranges differ
(function template) |
|
searches for the first occurrence of a range of elements
(function template) |
|
(C++20)
|
determines if two sets of elements are the same
(algorithm function object) |
function object implementing
x
==
y
(class template) |
|
returns range of elements matching a specific key
(function template) |