Sorry, not sure how to reply to this thread only (probably because I set my mailing list subscription to "digest once per day").

> `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.

This is exactly what I'm talking about. Why `if constexpr` can discard statements but boolean operations cannot?
I would imagine that the behaviour of the following two code snippets is identical:
```
if constexpr (a)
{
  if constexpr (b)
  {
    //do something
  }
}
```

```
if constexpr (a && b)
{
  //do something
}
```

But it is not in the case where `a` is true and `b` is not evaluatable.
Of course, `b` should still be checked for basic syntax the same way templates are checked even before they're instantiated.
You cannot compile a template with broken syntax but you can still write a template which doesn't make sense for specific types as long as you don't instantiate the template with those types.
I think the same logic should apply here. `b` should be valid only if it is instantiated/evaluated. And this instantiation should only happen if the expression's value is needed (i.e. `a` was true).
This is what I refer to as "short-circuiting".
Think of it as a lazy evaluation.
If `a` is false the compiler should not even consider evaluating `b` and should not generate any compilation errors if `b` is not a valid expression.

I realize I'm complaining about syntactic sugar but syntactic sugar is sometimes needed to adhere to the DRY principle and in this case I think it would make the code more readable and less error-prone. Also, it would make the generic world look and feel more like the runtime world.
I would go even further and add a constexpr ternary operator, so you can reduce code duplication even more. But that's a totally different topic.

--
Zamfir Yonchev

On Thu, Nov 17, 2022 at 2:00 PM <std-discussion-request@lists.isocpp.org> wrote:
Send Std-Discussion mailing list submissions to
        std-discussion@lists.isocpp.org

To subscribe or unsubscribe via the World Wide Web, visit
        https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion
or, via email, send a message with subject or body 'help' to
        std-discussion-request@lists.isocpp.org

You can reach the person managing the list at
        std-discussion-owner@lists.isocpp.org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Std-Discussion digest..."


Today's Topics:

   1. Re: short-circuiting logical operations on constexpr
      predicates (Jason McKesson)
   2. Re: short-circuiting logical operations on constexpr
      predicates (Edward Catmur)
   3. Re: short-circuiting logical operations on constexpr
      predicates (Thiago Macieira)


----------------------------------------------------------------------

Message: 1
Date: Wed, 16 Nov 2022 09:42:58 -0500
From: Jason McKesson <jmckesson@gmail.com>
To: std-discussion@lists.isocpp.org
Subject: Re: [std-discussion] short-circuiting logical operations on
        constexpr predicates
Message-ID:
        <CANLtd3UfeDJ53Hm5zJXHUv0hNp-c=Yfn0Q6MTRzm=OeWiioNUw@mail.gmail.com>
Content-Type: text/plain; charset="UTF-8"

On Wed, Nov 16, 2022 at 5:00 AM Zamfir Yonchev via Std-Discussion
<std-discussion@lists.isocpp.org> 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.


------------------------------

Message: 2
Date: Wed, 16 Nov 2022 15:02:26 +0000
From: Edward Catmur <ecatmur@googlemail.com>
To: std-discussion@lists.isocpp.org
Subject: Re: [std-discussion] short-circuiting logical operations on
        constexpr predicates
Message-ID:
        <CAJnLdOaTNma9xmW82jtKY0z4XYnBtCn++D5SyzARw37H6eCA1w@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

On Wed, 16 Nov 2022 at 14:44, Jason McKesson via Std-Discussion <
std-discussion@lists.isocpp.org> wrote:

> On Wed, Nov 16, 2022 at 5:00 AM Zamfir Yonchev via Std-Discussion
> <std-discussion@lists.isocpp.org> 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
-------------- next part --------------
HTML attachment scrubbed and removed

------------------------------

Message: 3
Date: Wed, 16 Nov 2022 11:17:22 -0800
From: Thiago Macieira <thiago@macieira.org>
To: std-discussion@lists.isocpp.org
Subject: Re: [std-discussion] short-circuiting logical operations on
        constexpr predicates
Message-ID: <1805684.QCnGb9OGeP@tjmaciei-mobl5>
Content-Type: text/plain; charset="us-ascii"

On Wednesday, 16 November 2022 06:42:58 PST Jason McKesson via Std-Discussion
wrote:
> 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`.

Note, this expression *does* make sense and is allowed. The first + is the
binary addition operator; all the rest are unary prefixes. So this expression
is

  a + (-(+(-(+c))))

If you remove the idempotent unary plus, you get

  a + (-(-c))

And two negations is the same as doing nothing (ignoring the UB at INT_MIN),
resulting in a simple addition

  a + c

Similarly, both a+++c and a---c are permitted, as are a*/*/*/c and a/*/*/*c.

None of those should pass a code review, of course.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel DCAI Cloud Engineering





------------------------------

Subject: Digest Footer

Std-Discussion mailing list
Std-Discussion@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion


------------------------------

End of Std-Discussion Digest, Vol 44, Issue 3
*********************************************