283. std::replace() requirement incorrect/insufficient

Section: 26.7.5 [alg.replace] Status: CD1 Submitter: Martin Sebor Opened: 2000-12-15 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [alg.replace].

View all issues with CD1 status.

Duplicate of: 483

Discussion:

(revision of the further discussion) There are a number of problems with the requires clauses for the algorithms in 25.1 and 25.2. The requires clause of each algorithm should describe the necessary and sufficient requirements on the inputs to the algorithm such that the algorithm compiles and runs properly. Many of the requires clauses fail to do this. Here is a summary of the kinds of mistakes:

  1. Use of EqualityComparable, which only puts requirements on a single type, when in fact an equality operator is required between two different types, typically either T and the iterator's value type or between the value types of two different iterators.
  2. Use of Assignable for T when in fact what was needed is Assignable for the value_type of the iterator, and convertability from T to the value_type of the iterator. Or for output iterators, the requirement should be that T is writable to the iterator (output iterators do not have value types).

Here is the list of algorithms that contain mistakes:

Also, in the requirements for EqualityComparable, the requirement that the operator be defined for const objects is lacking.

Proposed resolution:

20.1.1 Change p1 from

In Table 28, T is a type to be supplied by a C++ program instantiating a template, a, b, and c are values of type T.

to

In Table 28, T is a type to be supplied by a C++ program instantiating a template, a, b, and c are values of type const T.

25 Between p8 and p9

Add the following sentence:

When the description of an algorithm gives an expression such as *first == value for a condition, it is required that the expression evaluate to either true or false in boolean contexts.

25.1.2 Change p1 by deleting the requires clause.

25.1.6 Change p1 by deleting the requires clause.

25.1.9

Change p4 from

-4- Requires: Type T is EqualityComparable (20.1.1), type Size is convertible to integral type (4.7.12.3).

to

-4- Requires: The type Size is convertible to integral type (4.7.12.3).

25.2.4 Change p1 from

-1- Requires: Type T is Assignable (23.1 ) (and, for replace(), EqualityComparable (20.1.1 )).

to

-1- Requires: The expression *first = new_value must be valid.

and change p4 from

-4- Requires: Type T is Assignable (23.1) (and, for replace_copy(), EqualityComparable (20.1.1)). The ranges [first, last) and [result, result + (last - first)) shall not overlap.

to

-4- Requires: The results of the expressions *first and new_value must be writable to the result output iterator. The ranges [first, last) and [result, result + (last - first)) shall not overlap.

25.2.5 Change p1 from

-1- Requires: Type T is Assignable (23.1). The type Size is convertible to an integral type (4.7.12.3).

to

-1- Requires: The expression value must be is writable to the output iterator. The type Size is convertible to an integral type (4.7.12.3).

25.2.7 Change p1 from

-1- Requires: Type T is EqualityComparable (20.1.1).

to

-1- Requires: The value type of the iterator must be Assignable (23.1).

Rationale:

The general idea of the proposed solution is to remove the faulty requires clauses and let the returns and effects clauses speak for themselves. That is, the returns clauses contain expressions that must be valid, and therefore already imply the correct requirements. In addition, a sentence is added at the beginning of chapter 25 saying that expressions given as conditions must evaluate to true or false in a boolean context. An alternative would be to say that the type of these condition expressions must be literally bool, but that would be imposing a greater restriction that what the standard currently says (which is convertible to bool).