Created on 2024-12-05.00:00:00 last changed 2 weeks ago
Proposed resolution:
This wording is relative to N4993.
Modify [alg.search] as indicated:
template<class ForwardIterator1, class ForwardIterator2> constexpr ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2); […] template<class ExecutionPolicy, class ForwardIterator1, class ForwardIterator2, class BinaryPredicate> ForwardIterator1 search(ExecutionPolicy&& exec, ForwardIterator1 first1, ForwardIterator1 last1, ForwardIterator2 first2, ForwardIterator2 last2, BinaryPredicate pred);-1- Returns: The first iterator `i` in the range [first1, last1 - (last2 - first2)]
-2- […])such that for every nonnegative integer `n` less than `last2 - first2` the following corresponding conditions hold: `*(i + n) == *(first2 + n), pred(*(i + n)`, `*(first2 + n)) != false`. Returns `first1` if `[first2, last2)` is empty, otherwise returns `last1` if no such iterator is found.template<forward_iterator I1, sentinel_for<I1> S1, forward_iterator I2, sentinel_for<I2> S2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<I1, I2, Pred, Proj1, Proj2> constexpr subrange<I1> ranges::search(I1 first1, S1 last1, I2 first2, S2 last2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {}); template<forward_range R1, forward_range R2, class Pred = ranges::equal_to, class Proj1 = identity, class Proj2 = identity> requires indirectly_comparable<iterator_t<R1>, iterator_t<R2>, Pred, Proj1, Proj2> constexpr borrowed_subrange_t<R1> ranges::search(R1&& r1, R2&& r2, Pred pred = {}, Proj1 proj1 = {}, Proj2 proj2 = {});-3- Returns:
(3.1) — `{i, i + (last2 - first2)}`, where `i` is the first iterator in the range [first1, last1 - (last2 - first2)]
)such that for every non-negative integer `n` less than `last2 - first2` the conditionbool(invoke(pred, invoke(proj1, *(i + n)), invoke(proj2, *(first2 + n))))is `true`.
(3.2) — Returns `{last1, last1}` if no such iterator exists.
-4- […]
template<class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type> constexpr ForwardIterator search_n(ForwardIterator first, ForwardIterator last, Size count, const T& value); […] template<class ExecutionPolicy, class ForwardIterator, class Size, class T = iterator_traits<ForwardIterator>::value_type, class BinaryPredicate> ForwardIterator search_n(ExecutionPolicy&& exec, ForwardIterator first, ForwardIterator last, Size count, const T& value, BinaryPredicate pred);-5- […]
-6- […] -7- Returns: The first iterator `i` in the range [first, last-count])such that for every non-negative integer `n` less than `count` the condition E is `true`. Returns `last` if no such iterator is found. -8- […]template<forward_iterator I, sentinel_for<I> S, class Pred = ranges::equal_to, class Proj = identity, class T = projected_value_t<I, Proj>> requires indirectly_comparable<I, const T*, Pred, Proj> constexpr subrange<I> ranges::search_n(I first, S last, iter_difference_t<I> count, const T& value, Pred pred = {}, Proj proj = {}); template<forward_range R, class Pred = ranges::equal_to, class Proj = identity, class T = projected_value_t<iterator_t<R>, Proj>> requires indirectly_comparable<iterator_t<R>, const T*, Pred, Proj> constexpr borrowed_subrange_t<R> ranges::search_n(R&& r, range_difference_t<R> count, const T& value, Pred pred = {}, Proj proj = {});-9- Returns: `{i, i + count}` where `i` is the first iterator in the range [first, last - count]
-10- […])such that for every non-negative integer `n` less than `count`, the following condition holds: `invoke(pred, invoke(proj, *(i + n)), value)`. Returns `{last, last}` if no such iterator is found.
[ 2024-12-07; Daniel comments and provides wording ]
The mentioned wording issue is present in all previous standard versions, including the SGI STL. It needs to be fixed in all search variants specified in [alg.search] (except for the form using a `Searcher`).
Originally reported as editorial request #7474:
During the qualification of the C++ STL Validas has pointed me to the following issue: The specification of [alg.search] has a wrong range. Currently the range is "[first1, last1 - (last2 - first2))" (exclusive) but should be "[first1, last1 - (last2 - first2)]" (inclusive). So please correct the closing ")" to "]". Otherwise the last occurrence will not be found. We observed the issue in C++14 and C++17 and cppreference.com. The implementations do the right thing and work correctly and find even the last occurrence. For example in the list `{1, 2, 3, 4, 5}` the pattern `{4, 5}` should be found (obviously). In the case the last element is not included it will not be found. Demonstration on godbolt shows that the implementation is working and finds the pattern.History | |||
---|---|---|---|
Date | User | Action | Args |
2024-12-07 14:44:28 | admin | set | messages: + msg14516 |
2024-12-07 14:44:28 | admin | set | messages: + msg14515 |
2024-12-05 00:00:00 | admin | create |