4132. Throws specifications need to include boolean-testable operations

Section: 23.2.7.1 [associative.reqmts.general], 23.3.9.5 [list.ops], 23.3.7.6 [forward.list.ops] Status: New Submitter: Daniel Krügler Opened: 2024-08-03 Last modified: 2024-10-02

Priority: 3

View other active issues in [associative.reqmts.general].

View all other issues in [associative.reqmts.general].

View all issues with New status.

Discussion:

The standard provides various Throws: elements whose specification refers to boolean-like expressions, for example 23.3.9.5 [list.ops] says:

-17- Throws: Nothing unless an exception is thrown by *i == value or pred(*i) != false.

The expressions *i == value (by [tab:cpp17.equalitycomparable]) and pred(*i) (by 26.2 [algorithms.requirements]) both require to have a type that models boolean-testable, so their actual evaluation potentially requires an additional conversion to bool (The part "!= false" was not guaranteed to realize that as pointed out by LWG 4127 and will therefore be removed by that issue).

The boolean-testable requirements (18.5.2 [concept.booleantestable]) doesn't say anything about potential exceptions thrown by this conversion, so we must assume that this conversion allows an exception to be thrown.

An additional problem arises by the fact that the boolean-testable requirements do not require that the implicit and explicit conversion to bool have to behave consistently in regard to exceptions. 18.4.4 [concept.convertible] only says that "The implicit and explicit conversions are required to produce equal results". But since we don't want to restrict implementations to a specific bool conversion, the Throws wording should include it in a manner that applies to any form.

Besides the obviously necessary conversion to bool we should not restrict implementations in regard to the potential usage of other boolean-testable operations, e.g. negation, which could potentially also throw an exception.

Therefore the wording for the affected Throws: elements somehow needs to mention boolean-testable operations to cover the effective operation that is involved here without actually restricting existing implementations unnecessarily.

Previous resolution [SUPERSEDED]:

This wording is relative to N4986.

  1. Modify 23.2.7.1 [associative.reqmts.general] as indicated:

    a.merge(a2)
    

    […]

    -116- Throws: Nothing unless the evaluation of the comparison object including every selected boolean-testable (18.5.2 [concept.booleantestable]) operation throws.

  2. Modify 23.3.7.6 [forward.list.ops] as indicated:

    size_type remove(const T& value);
    template<class Predicate> size_type remove_if(Predicate pred);
    

    […]

    -15- Throws: Nothing unless an exception is thrown by the equality comparison or the predicate evaluation including every selected boolean-testable (18.5.2 [concept.booleantestable]) operation.

    […]

    size_type unique();
    template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);
    

    […]

    -22- Throws: Nothing unless an exception is thrown by the predicate evaluation including every selected boolean-testable (18.5.2 [concept.booleantestable]) operation.

  3. Modify 23.3.9.5 [list.ops] as indicated:

    [Drafting note: The adjustment of p17 is presented as if issue LWG 4127 proposed wording has already been applied]

    size_type remove(const T& value);
    template<class Predicate> size_type remove_if(Predicate pred);
    

    […]

    -17- Throws: Nothing unless an exception is thrown by *i == value or pred(*i) including every selected boolean-testable (18.5.2 [concept.booleantestable]) operation.

    […]

    size_type unique();
    template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);
    

    […]

    -24- Throws: Nothing unless an exception is thrown by the predicate evaluation including every selected boolean-testable (18.5.2 [concept.booleantestable]) operation.

    […]

[2024-09-07; Daniel comments and improves wording]

During LWG reflector discussion it has been proposed to add similar wording to the throwing prohibition in Cpp17NullablePointer and nothrow-sentinel-for, too. Furthermore, the existing wording changes are becoming now more harmonized in their stylistic forms.

[2024-10-02; Reflector poll]

Set priority to 3 after reflector poll.

Proposed resolution:

This wording is relative to N4988.

  1. Modify 16.4.4.4 [nullablepointer.requirements] as indicated:

    -4- No operation which is part of the Cpp17NullablePointer requirements, including each of its boolean-testable (18.5.2 [concept.booleantestable]) operations, shall exit via an exception.

  2. Modify 23.2.7.1 [associative.reqmts.general] as indicated:

    a.merge(a2)
    

    […]

    -116- Throws: Nothing unless an exception is thrown by evaluation of the comparison object, including any selected boolean-testable (18.5.2 [concept.booleantestable]) operationsthrows.

  3. Modify 23.3.7.6 [forward.list.ops] as indicated:

    size_type remove(const T& value);
    template<class Predicate> size_type remove_if(Predicate pred);
    

    […]

    -15- Throws: Nothing unless an exception is thrown by the equality comparison (for remove()) or the predicate (for remove_if()), including any selected boolean-testable (18.5.2 [concept.booleantestable]) operations.

    […]

    size_type unique();
    template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);
    

    […]

    -22- Throws: Nothing unless an exception is thrown by evaluation of the predicate, including any selected boolean-testable (18.5.2 [concept.booleantestable]) operations.

  4. Modify 23.3.9.5 [list.ops] as indicated:

    [Drafting note: The adjustment of p17 is presented as if issue LWG 4127 proposed wording has already been applied]

    size_type remove(const T& value);
    template<class Predicate> size_type remove_if(Predicate pred);
    

    […]

    -17- Throws: Nothing unless an exception is thrown by *i == value or pred(*i)the equality comparison (for remove()) or evaluation of the predicate (for remove_if()), including any selected boolean-testable (18.5.2 [concept.booleantestable]) operations.

    […]

    size_type unique();
    template<class BinaryPredicate> size_type unique(BinaryPredicate binary_pred);
    

    […]

    -24- Throws: Nothing unless an exception is thrown by evaluation of the predicate, including any selected boolean-testable (18.5.2 [concept.booleantestable]) operations.

    […]

  5. Modify 26.11.2 [special.mem.concepts] as indicated:

    template<class S, class I>
    concept nothrow-sentinel-for = sentinel_for<S, I>; // exposition only
    

    -4- Types S and I model nothrow-sentinel-for only if no exceptions are thrown from copy construction, move construction, copy assignment, move assignment, or comparisons , including each of its boolean-testable (18.5.2 [concept.booleantestable]) operations, between valid values of type I and S.

    -5- [Note 2: This concept allows some sentinel_for (24.3.4.7 [iterator.concept.sentinel]) operations to throw exceptions. — end note]