C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Manifold comparison operator

From: Breno Guimarães <brenorg_at_[hidden]>
Date: Thu, 7 Sep 2023 19:15:39 -0300
It should be possible to write a template that looks more readable:

if (matcher(var).is_none_of(opt1, opt2, opt3))

Was that considered?

Best regards,
Breno G

Em qui., 7 de set. de 2023 18:56, Ben Crowhurst via Std-Proposals <
std-proposals_at_[hidden]> escreveu:

> We propose a new range of conditional operators for C++:
>
> * [^] one-of
> * [&] all-of
> * [|] any-of
> * [!] none-of
>
> These operators simplify common code patterns and improve the clarity of
> basic conditional expressions.
>
>
> 1 ) Before/After
> Sample code is taken from the llvm-project
> (clang/lib/StaticAnalyzer/Checkers/SmartPtrModeling.cpp).
>
> Before the proposal:
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (!(OOK == OO_EqualEqual || OOK == OO_ExclaimEqual || OOK == OO_Less
> ||
> OOK == OO_LessEqual || OOK == OO_Greater || OOK ==
> OO_GreaterEqual ||
> OOK == OO_Spaceship))
> return false;
>
> After the proposal:
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (OOK [!] OO_EqualEqual, OO_ExclaimEqual, OO_Less, OO_LessEqual,
> OO_Greater,
> OO_GreaterEqual, OO_Spaceship)
> return false;
>
> 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.
>
>
> 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.
>
>
> 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.
>
> 4.1) Macro solution
>
> #define NONE_OF0(lhs, rhs, ...) lhs != rhs
> #define NONE_OF1(lhs, rhs, ...) lhs != rhs && NONE_OF0(lhs, __VA_ARGS__)
> // Add NONE_OF2, 3, 4, 5... as desired.
> #define NONE_OF(lhs, ...) NONE_OF1(lhs, __VA_ARGS__)
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (NONE_OF(OOK, OO_EqualEqual, OO_ExclaimEqual, OO_Less, OO_LessEqual,
> OO_Greater, OO_GreaterEqual, OO_Spaceship))
> return false;
>
> A macro solution is hard to debug, verbose, specific to the desired number
> of potential arguments, and fails to clearly communicate the intent;
> comparison LHS appears as the first argument.
>
> 4.2) Template solution
>
> template <typename LHS, typename... Args>
> auto none_of(LHS lhs, Args... args)
> {
> const auto predicate = std::not_equal_to<LHS>();
> return (predicate(lhs, args) && ...);
> }
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (none_of(OOK, OO_EqualEqual, OO_ExclaimEqual, OO_Less, OO_LessEqual,
> OO_Greater, OO_GreaterEqual, OO_Spaceship))
> return false;
>
> Much improved over the macro solution, yet fails to clearly communicate
> the intent without understanding the internals; comparison LHS appears as
> the first argument.
>
> 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.
>
> 4.4) Helper function solution
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (is_not_comparison_operator(OOK))
> return false;
>
> Provides a clean and concise meaning towards control flow, however, it
> results in the proliferation of many helper functions to address all
> possible combinations throughout a codebase e.g. is_comparison_operator,
> is_equality_operator, is_not_equality_operator, etc.
>
> In more involved scenarios this approach becomes unwieldy, as dynamic
> aspects must be passed into the function as arguments or expansion of the
> condition must occur i.e.
>
> const OverloadedOperatorKind OOK = FD->getOverloadedOperator();
> if (is_not_comparison_operator(OOK) && OOK != NextToken().getKind())
> return false;
>
>
> 5) Impact on the Standard
> The newly proposed syntax is ill-formed in the current working draft.
> This is a core language extension.
>
>
> 6) Proposed wording
> Section '7.6 Compound expressions' requires the addition of new grammar
> and wording detailing the Manifold operator syntax. TBD.
>
>
> 7) Implementation
>
> A rudimentary implementation was crafted into the llvm-project to
> determine the impact on existing compiler infrastructure.
>
> * Lex library - Addition of new manifold tokens.
> * Parse library - Modification of binary expression parsing to emit
> equivalent entries into the AST.
>
> Minimal changes were required.
>
>
> Thank you for your time.
>
> Regards,
> Ben Crowhurst
>
>
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2023-09-07 22:15:37