C++ Logo

std-discussion

Advanced search

Re: short-circuiting logical operations on constexpr predicates

From: Edward Catmur <ecatmur_at_[hidden]>
Date: Wed, 16 Nov 2022 15:02:26 +0000
On Wed, 16 Nov 2022 at 14:44, Jason McKesson via Std-Discussion <
std-discussion_at_[hidden]> wrote:

> On Wed, Nov 16, 2022 at 5:00 AM Zamfir Yonchev via Std-Discussion
> <std-discussion_at_[hidden]> wrote:
> >
> > Hi,
> >
> > I was wondering why the language doesn't support short-circuiting on
> logical operations in constexpr context.
>
> It does. The rules of short-circuit evaluation don't change because
> something is in a constant expression. Your problem is not a lack of
> short-circuit evaluation; your problem is that short-circuit
> evaluation doesn't mean what you think it does.
>
> `std::invoke_result_t<F, T>` is ill-formed if `F` is not invokable.
> That is not a matter of expression evaluation; that's a matter of
> template instantiation. It's not the result of the evaluation that is
> ill-formed; it's the *existence* of the expression itself. The literal
> text of the source code makes no sense, as far as the language is
> concerned. It is no different than if you wrote `a + - + - + c`.
>
> The compiler doesn't get to the point where it would even consider
> evaluating the expression because the code doesn't make sense.
>
> `if constexpr` has explicit rules allowing it to discard statements
> depending on the result of the constant expression. But that is a
> special grammatical construct explicitly designed with this
> functionality in mind.
>
> So the reason why what you wrote doesn't work is because there is no
> special expression-level construct that was added to the language to
> allow discarding of subexpressions in the same way that `if constexpr`
> can discard statements.
>

Ahem. Actually, we do have such a construct in the evaluation of
constraints. You can make use of that mode by wrapping your test in
`requires requires`:

  constexpr bool test = requires { requires std::is_invocable_v<F, T> &&
std::is_same_v<std::invoke_result_t<F, T>, int>; };

Demo: https://godbolt.org/z/7q5dvKnsn

https://eel.is/c++draft/expr.prim.req.general#5.sentence-3

Received on 2022-11-16 15:02:40