Created on 2024-07-25.00:00:00 last changed 16 months ago
Proposed resolution:
This wording is relative to N4988.
Modify [func.search.bm] as indicated:
boyer_moore_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());-1- Preconditions: The value type of
-2- LetRandomAccessIterator1meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.Vbeiterator_traits<RandomAccessIterator1>::value_type. For any two valuesAandBof typeV, ifpred(A, B)is true, then== truehf(A) == hf(B)istrue. […]template<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;[…]
-7- Returns: A pair of iteratorsiandjsuch that
(7.1) —
iis the first iterator in the range [first,last - (pat_last_ - pat_first_)) such that for every non-negative integernless thanpat_last_ - pat_first_the following condition holds:pred(*(i + n), *(pat_first_ + n))is true, and!= false(7.2) — j == next(i, distance(pat_first_, pat_last_)) is true.
Modify [func.search.bmh] as indicated:
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());-1- Preconditions: The value type of
-2- LetRandomAccessIterator1meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.Vbeiterator_traits<RandomAccessIterator1>::value_type. For any two valuesAandBof typeV, ifpred(A, B), then==is truehf(A) == hf(B)istrue. […]template<class RandomAccessIterator2> pair<RandomAccessIterator2, RandomAccessIterator2> operator()(RandomAccessIterator2 first, RandomAccessIterator2 last) const;[…]
-7- Returns: A pair of iteratorsiandjsuch that
(7.1) —
iis the first iterator in the range [first,last - (pat_last_ - pat_first_)) such that for every non-negative integernless thanpat_last_ - pat_first_the following condition holds:pred(*(i + n), *(pat_first_ + n))is true, and!= false(7.2) — j == next(i, distance(pat_first_, pat_last_)) is true.
Modify [associative.reqmts.general] as indicated:
-3- The phrase "equivalence of keys" means the equivalence relation imposed by the comparison object. That is, two keys
[…]k1andk2are considered to be equivalent if for the comparison objectcomp,!comp(k1, k2)is true.== false&& !comp(k2, k1)== false-177- The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them. For any two dereferenceable iterators
iandjsuch that distance fromitojis positive, the following condition holds:!value_comp(*j, *i)
== falseis true.-178- For associative containers with unique keys the stronger condition holds:
value_comp(*i, *j)
!= falseis true.
Modify [list.ops] as indicated:
size_type remove(const T& value); template<class Predicate> size_type remove_if(Predicate pred);-15- Effects: Erases all the elements in the list referred to by a list iterator
-16- Returns: The number of elements erased. -17- Throws: Nothing unless an exception is thrown byifor which the following conditions hold: *i == value is true, pred(*i)!= falseis true. Invalidates only the iterators and references to the erased elements.*i == valueorpred(*i). […]!= false
Modify [alg.find] as indicated:
[Drafting note: Sub-bullets (1.4), (1.5), and (1.6) below regarding invoke expressions are similarly required model boolean-testable, as specified by concept predicate ([concept.predicate]), therefore the explicit conversion is removed here for consistency]
-1- Let E be:
(1.1) —
*i == valueforfind;(1.2) —
pred(*i)for!= falsefind_if;(1.3) —
!pred(*i)for== falsefind_if_not;(1.4) —
bool(invoke(proj, *i) == value)for ranges::find;(1.5) —
bool(invoke(pred, invoke(proj, *i)))for ranges::find_if;(1.6) —
bool(!invoke(pred, invoke(proj, *i)))for ranges::find_if_not.-2- Returns: The first iterator i in the range [first, last) for which E is true. Returns last if no such iterator is found.
Modify [alg.find.first.of] as indicated:
-1- Let E be:
(1.1) —
*i == *jfor the overloads with no parameterpred;(1.2) —
pred(*i, *j)for the overloads with a parameter!= falsepredand no parameterproj1;(1.3) —
bool(invoke(pred, invoke(proj1, *i), invoke(proj2, *j)))for the overloads with parameters pred and proj1.[…]
-3- Returns: The first iterator i in the range [first1, last1) such that for some iterator j in the range [first2, last2) Eholdsis true. Returns last1 if [first2, last2) is empty or if no such iterator is found.
Modify [alg.adjacent.find] as indicated:
-1- Let E be:
(1.1) —
*i == *(i + 1)for the overloads with no parameterpred;(1.2) —
pred(*i, *(i + 1))for the overloads with a parameter!= falsepredand no parameterproj;(1.3) —
bool(invoke(pred, invoke(proj, *i), invoke(proj, *(i + 1))))for the overloads with both parameters pred and proj.-2- Returns: The first iterator i such that both i and i + 1 are in the range [first, last) for which E
holdsis true. Returns last if no such iterator is found.
Modify [alg.count] as indicated:
-1- Let E be:
(1.1) —
*i == valuefor the overloads with no parameterpredorproj;(1.2) —
pred(*i)for the overloads with a parameter!= falsepredbut no parameterproj;(1.3) — invoke(proj, *i) == value for the overloads with a parameter proj but no parameter pred;
(1.4) —
bool(invoke(pred, invoke(proj, *i)))for the overloads with both parameters proj and pred.-2- Effects: Returns the number of iterators i in the range [first, last) for which E
holdsis true.
Modify [alg.mismatch] as indicated:
-2- Let E be:
(2.1) —
!(*(first1 + n) == *(first2 + n))for the overloads with no parameterpred;(2.2) —
!pred(*(first1 + n), *(first2 + n))for the overloads with a parameter== falsepredand no parameterproj1;(2.3) — !invoke(pred, invoke(proj1, *(first1 + n)), invoke(proj2, *(first2 + n))) for the overloads with both parameters pred and proj1.
[…]
-4- Returns: { first1 + n, first2 + n }, where n is the smallest integer in [0, N) such that Eholdsis true, or N if no such integer exists.
Modify [alg.search] as indicated:
-1- Returns: The first iterator
[…]iin the range [first1,last1 - (last2-first2)) such that for every non-negative integernless thanlast2 - first2the following corresponding conditions hold: *(i + n) == *(first2 + n) is true, pred(*(i + n), *(first2 + n))!= falseis true. Returnsfirst1if [first2,last2) is empty, otherwise returnslast1if no such iterator is found.-6- Let E be pred(*(i + n), value)
-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.!= falsefor the overloads with a parameter pred, and *(i + n) == value otherwise.
Modify [alg.sorting.general] as indicated:
[Drafting note: The wording below does not require extra "is true" added to the adjusted expressions. This is comparable to the E cases above, since [alg.sorting.general] p2 already points out:
The return value of the function call operation applied to an object of type Compare, when converted to bool, yields true if the first argument of the call is less than the second, and false otherwise.
]
-3- For all algorithms that take
Compare, there is a version that usesoperator<instead. That is,comp(*i, *j)defaults to!= false*i < *j. For algorithms other than those described in [alg.binary.search],!= falsecompshall induce a strict weak ordering on the values.
[ 2024-08-03; Daniel provides improved wording ]
The current wording is inconsistent in regard to explicit conversion to bool and lack of them in cases of expressions whose value is required to satisfy the boolean-testable constraints. To realize consistent results for all subclause references touched by the changes required by this issue I decided that every E definition remains unconverted but and that every E evaluation is interpreted as if an implied bool conversion has been applied based on the reflector preference for that simplified approach.
Nonetheless, during the wording preparation I noticed that the wording in the Throws: element [list.ops] p17 is seriously missing the additional extra conversion to bool for both expressions, because the boolean-testable requirements do not impose a no-throw requirement for that conversion, and they must therefore be included here. This problem will be handled by a separate issue (LWG 4132), because the rationale for this change is different from the actual target of this issue and not related to the other consistency adjustments done by the wording below.[ 2024-08-02; Reflector poll ]
Set priority to 3 after reflector poll. "Needs more 'is `true`' added". "Would prefer not to have explicit conversions to `bool` unless `boolean-testable` requires that. The 'Let E be' lists don't need an 'is true' there, but the use of 'E' should say 'is true'". [alg.search] and [func.search.bm] have changed editorially in the draft, the proposed resolution needs updating.
This wording is relative to N4986.
Modify [func.search.bm] as indicated:
boyer_moore_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());-1- Preconditions: The value type of
-2- LetRandomAccessIterator1meets the Cpp17DefaultConstructible, the Cpp17CopyConstructible, and the Cpp17CopyAssignable requirements.Vbeiterator_traits<RandomAccessIterator1>::value_type. For any two valuesAandBof typeV, ifpred(A, B), then== truehf(A) == hf(B)istrue. […]-7- Returns: A pair of iterators
iandjsuch that
(7.1) —
iis the first iterator in the range [first,last - (pat_last_ - pat_first_)) such that for every non-negative integernless thanpat_last_ - pat_first_the following condition holds:pred(*(i + n), *(pat_first_ + n)), and!= false[…]
Modify [func.search.bmh] as indicated:
boyer_moore_horspool_searcher(RandomAccessIterator1 pat_first, RandomAccessIterator1 pat_last, Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());-1- Preconditions: The value type of
-2- LetRandomAccessIterator1meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.Vbeiterator_traits<RandomAccessIterator1>::value_type. For any two valuesAandBof typeV, ifpred(A, B), then== truehf(A) == hf(B)istrue. […]-7- Returns: A pair of iterators
iandjsuch that
(7.1) —
iis the first iterator in the range [first,last - (pat_last_ - pat_first_)) such that for every non-negative integernless thanpat_last_ - pat_first_the following condition holds:pred(*(i + n), *(pat_first_ + n)), and!= false[…]
Modify [associative.reqmts.general] as indicated:
-3- The phrase "equivalence of keys" means the equivalence relation imposed by the comparison object. That is, two keys
[…]k1andk2are considered to be equivalent if for the comparison objectcomp,!comp(k1, k2).== false&& !comp(k2, k1)== false-177- The fundamental property of iterators of associative containers is that they iterate through the containers in the non-descending order of keys where non-descending is defined by the comparison that was used to construct them. For any two dereferenceable iterators
iandjsuch that distance fromitojis positive, the following condition holds:!value_comp(*j, *i)== false-178- For associative containers with unique keys the stronger condition holds:
value_comp(*i, *j)!= false
Modify [list.ops] as indicated:
size_type remove(const T& value); template<class Predicate> size_type remove_if(Predicate pred);-15- Effects: Erases all the elements in the list referred to by a list iterator
-16- Returns: The number of elements erased. -17- Throws: Nothing unless an exception is thrown byifor which the following conditions hold:*i == value, pred(*i). Invalidates only the iterators and references to the erased elements.!= false*i == valueorpred(*i). […]!= false
Modify [alg.find] as indicated:
-1- Let E be:
(1.1) —
*i == valueforfind;(1.2) —
pred(*i)for!= falsefind_if;(1.3) —
[…]!pred(*i)for== falsefind_if_not;
Modify [alg.find.first.of] as indicated:
-1- Let E be:
(1.1) —
*i == *jfor the overloads with no parameterpred;(1.2) —
[…]pred(*i, *j)for the overloads with a parameter!= falsepredand no parameterproj1;
Modify [alg.adjacent.find] as indicated:
-1- Let E be:
(1.1) —
*i == *(i + 1)for the overloads with no parameterpred;(1.2) —
[…]pred(*i, *(i + 1))for the overloads with a parameter!= falsepredand no parameterproj1;
Modify [alg.count] as indicated:
-1- Let E be:
(1.1) —
*i == valuefor the overloads with no parameterpredorproj;(1.2) —
[…]pred(*i)for the overloads with a parameter!= falsepredbut no parameterproj;
Modify [alg.mismatch] as indicated:
-2- Let E be:
(2.1) —
!(*(first1 + n) == *(first2 + n))for the overloads with no parameterpred;(2.2) —
[…]!pred(*(first1 + n), *(first2 + n))for the overloads with a parameter== falsepredand no parameterproj1;
Modify [alg.search] as indicated:
-1- Returns: The first iterator
[…]iin the range [first1,last1 - (last2-first2)) such that for every non-negative integernless thanlast2 - first2the following corresponding conditions hold:*(i + n) == *(first2 + n), pred(*(i + n), *(first2 + n)). Returns!= falsefirst1if [first2,last2) is empty, otherwise returnslast1if no such iterator is found.-6- Returns: The first iterator
iin the range [first,last-count) such that for every non-negative integernless thancountthe following corresponding conditions hold:*(i + n) == value, pred(*(i + n), value). Returns!= falselastif no such iterator is found.
Modify [alg.sorting.general] as indicated:
-3- For all algorithms that take
Compare, there is a version that usesoperator<instead. That is,comp(*i, *j)defaults to!= false*i < *j. For algorithms other than those described in [alg.binary.search],!= falsecompshall induce a strict weak ordering on the values.
[ 2024-07-27; Daniel comments ]
I would recommend to add a wrapping "bool(pred([…]))" and possibly even extend to "bool(pred([…])) is true" following our usual wording convention, since an English phrase of the form "if pred([…])" where pred([…]) is potential non-bool and the English "if" is not a C++ language if (with built-in conversion semantics) doesn't sound like a meaningful phrase to me.
The boolean-testable concept introduced in P1964R2
places appropriate constraints on boolean-ish types, so that !pred(x) or
i != last && pred(*i) always has a valid definition.
decltype(pred(*first)) should model boolean-testable.
However, boolean-testable does not guarantee that
pred(*i) != false is valid, because the type may overload operator==.
It is necessary to replace this form of expression with an appropriate one as we do in
P1964R2.
| History | |||
|---|---|---|---|
| Date | User | Action | Args |
| 2024-08-03 17:00:40 | admin | set | messages: + msg14307 |
| 2024-08-02 21:52:03 | admin | set | messages: + msg14296 |
| 2024-07-27 14:44:32 | admin | set | messages: + msg14276 |
| 2024-07-27 14:44:32 | admin | set | messages: + msg14275 |
| 2024-07-25 00:00:00 | admin | create | |