Created on 2024-07-25.00:00:00 last changed 4 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- LetRandomAccessIterator1
meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.V
beiterator_traits<RandomAccessIterator1>::value_type
. For any two valuesA
andB
of 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 iteratorsi
andj
such that
(7.1) —
i
is the first iterator in the range [first
,last - (pat_last_ - pat_first_)
) such that for every non-negative integern
less 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- LetRandomAccessIterator1
meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.V
beiterator_traits<RandomAccessIterator1>::value_type
. For any two valuesA
andB
of 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 iteratorsi
andj
such that
(7.1) —
i
is the first iterator in the range [first
,last - (pat_last_ - pat_first_)
) such that for every non-negative integern
less 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
[…]k1
andk2
are 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
i
andj
such that distance fromi
toj
is 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 byi
for which the following conditions hold: *i == value is true, pred(*i)!= falseis true. Invalidates only the iterators and references to the erased elements.*i == value
orpred(*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 == value
forfind
;(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 == *j
for the overloads with no parameterpred
;(1.2) —
pred(*i, *j)
for the overloads with a parameter!= falsepred
and 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!= falsepred
and 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 == value
for the overloads with no parameterpred
orproj
;(1.2) —
pred(*i)
for the overloads with a parameter!= falsepred
but 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== falsepred
and 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
[…]i
in the range [first1
,last1 - (last2-first2)
) such that for every non-negative integern
less thanlast2 - first2
the following corresponding conditions hold: *(i + n) == *(first2 + n) is true, pred(*(i + n), *(first2 + n))!= falseis true. Returnsfirst1
if [first2
,last2
) is empty, otherwise returnslast1
if 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],!= falsecomp
shall 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- LetRandomAccessIterator1
meets the Cpp17DefaultConstructible, the Cpp17CopyConstructible, and the Cpp17CopyAssignable requirements.V
beiterator_traits<RandomAccessIterator1>::value_type
. For any two valuesA
andB
of typeV
, ifpred(A, B)
, then== truehf(A) == hf(B)
istrue
. […]-7- Returns: A pair of iterators
i
andj
such that
(7.1) —
i
is the first iterator in the range [first
,last - (pat_last_ - pat_first_)
) such that for every non-negative integern
less 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- LetRandomAccessIterator1
meets the Cpp17DefaultConstructible, Cpp17CopyConstructible, and Cpp17CopyAssignable requirements.V
beiterator_traits<RandomAccessIterator1>::value_type
. For any two valuesA
andB
of typeV
, ifpred(A, B)
, then== truehf(A) == hf(B)
istrue
. […]-7- Returns: A pair of iterators
i
andj
such that
(7.1) —
i
is the first iterator in the range [first
,last - (pat_last_ - pat_first_)
) such that for every non-negative integern
less 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
[…]k1
andk2
are 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
i
andj
such that distance fromi
toj
is 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 byi
for which the following conditions hold:*i == value, pred(*i)
. Invalidates only the iterators and references to the erased elements.!= false*i == value
orpred(*i)
. […]!= false
Modify [alg.find] as indicated:
-1- Let E be:
(1.1) —
*i == value
forfind
;(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 == *j
for the overloads with no parameterpred
;(1.2) —
[…]pred(*i, *j)
for the overloads with a parameter!= falsepred
and 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!= falsepred
and no parameterproj1
;
Modify [alg.count] as indicated:
-1- Let E be:
(1.1) —
*i == value
for the overloads with no parameterpred
orproj
;(1.2) —
[…]pred(*i)
for the overloads with a parameter!= falsepred
but 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== falsepred
and no parameterproj1
;
Modify [alg.search] as indicated:
-1- Returns: The first iterator
[…]i
in the range [first1
,last1 - (last2-first2)
) such that for every non-negative integern
less thanlast2 - first2
the following corresponding conditions hold:*(i + n) == *(first2 + n), pred(*(i + n), *(first2 + n))
. Returns!= falsefirst1
if [first2
,last2
) is empty, otherwise returnslast1
if no such iterator is found.-6- Returns: The first iterator
i
in the range [first
,last-count
) such that for every non-negative integern
less thancount
the following corresponding conditions hold:*(i + n) == value, pred(*(i + n), value)
. Returns!= falselast
if 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],!= falsecomp
shall 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 |