C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Manifold comparison operator

From: Julien Jorge <julien.jorge_at_[hidden]>
Date: Fri, 8 Sep 2023 08:44:48 +0200
On 07/09/2023 11:03, Ben Crowhurst via Std-Proposals wrote:
> 2) Proposal
> There is one conditional operator in the C++ standard :? (Ternary). We propose to expand this horizon with four additional operators.
>
> Operator Statement Equivalence
>
> one of if (var [^] val1, val2) E; if ((var == val1 && var != val2) || (var != val1 && var == val2)) E;
>
> all of if (var [&] val1, val2) E; if (var == val1 && var == val2) E;
>
> any of if (var [|] val1, val2) E; if (var == val1 || var == val2) E;
>
> none of if (var [!] val1, val2) E; if (var != val1 && var != val2) E;
>
> As is the case with the Ternary operator, no overloading will be supported. This ensures that conditional operands are only evaluated based on the truth or falseness of the conditional expression.
>
> The Comma operator will NOT be interpreted during the evaluation of the right-hand side of a Manifold operator.
>
How should the compiler parse statements like the following?

    bool t = var1 [&] val1, val2, var2 [|] val3, val4, val5;

Is it

    var1 == val1 && var1 == val2 && (var2 == val3 || var2 == val4) &&
    var1 == val5

Or

    var1 == val1 && var1 == val2 && (var2 == val3 || var2 == val4 ||
    var2 == val5)

Or something else?

> 4.3) STL solution
> std::all_of, std::any_of, std::none_of and std::ranges equivalent.
>
> const std::set<OverloadedOperatorKind> ComparisonOperators = {
> OO_EqualEqual, OO_ExclaimEqual, OO_Less, OO_LessEqual, OO_Greater,
> OO_GreaterEqual, OO_Spaceship
> };
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (std::none_of(std::cbegin(ComparisonOperators),
> std::cend(ComparisonOperators),
> [&](auto op) { return op == OOK; }))
> return false;
>
> The STL solution presents a verbose conditional construction and is not easily capable of handling variables, literals, and functional call-sites without increasing code complexity. Additionally, there is no support for std::one_of.

If you must compare with the STL version I think you should use the
range algorithms and skip the std::set, something like:

    static constexpr op comparison_operators[] = {
       OO_EqualEqual, OO_ExclaimEqual, OO_Less, OO_LessEqual,
       OO_Greater, OO_GreaterEqual, OO_Spaceship
    };

    const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
    if (std::ranges::none_of(comparison_operators,
                              [=](op c) -> bool { return OOK == c; })
       return false;

> These operators simplify common code patterns and improve the clarity of basic conditional expressions.
> […]
> Resulting in a 21.7% decrease in character count and a reduction in cognitive load, with no requirement to study each comparison operator delimited by subsequent logical operators.
> […]
>
> 3) Motivation
> To improve code clarity when interpreting multifaceted conditionals.
>
> 4) Alternatives
> A number of alternative solutions exist, however, all inflict increasing code complexity and distract from interpreting the program control flow.

These statements seem quite subjective and I would avoid justifying new
syntax in the sake of code clarity for this reason. Clearly, we do not
use the same metric to measure code clarity ;) On the contrary I would
argue that anyone with a basic knowledge of English can infer the
meaning of `std::any_of` while nobody except C++ experts will know the
meaning of [&], thus `std::any_of` is preferable.

Best regards,

Julien

Received on 2023-09-08 06:44:51