C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Attribute [[discard]] and attributes on expressions

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Fri, 6 Oct 2023 10:23:00 -0400
On Fri, Oct 6, 2023 at 9:45 AM Giuseppe D'Angelo via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On 06/10/2023 11:30, Ferhat Geçdoğan via Std-Proposals wrote:
> > Is there any useful use-case that makes [[discard]] unique? That's just
> > a way of adding one more unuseful C++ keyword to the list in my opinion.
>
> It's not a new keyword, it's an attribute.
>

But if EWG thinks it "has an effect," they'll ask to make it a keyword. ;)
If we s/keyword/syntactic feature/, I agree with Ferhat's point. (As you
know; I know I'm repeating myself needlessly here. :))

* It does not abuse the cast notation and the cast semantics towards
> void in order to suppress a warning. Doing a cast to void (à la
> `(void)f();`) isn't done because one wants a specific type conversion,
> it's done to silence the [[nodiscard]] warning.


Well, it occurred to me this morning that (void) has another very nice
synergy. Remember how we said yesterday that nobody should ever use the
comma operator for anything? Well, today I'm walking back from that
position a little bit. Library implementors use it a lot, in the context of
the three-part for loop:
    for (int i = 0; i < n; ++i, (void)update(n))
In this context, (void) has two reasons to exist:
- It indicates that we're discarding the value of `update` (which let's
assume is a user-provided function that the library doesn't know what it
returns)
- It suppresses ADL on that `operator,` in case the user-provided `advance`
returns some type `Evil`
    struct Evil { friend void operator,(int, Evil) { puts("ha ha"); } };

That is, (void) coincidentally-or-not fits the bill for these library
implementors exactly.
Your proposed [[discard]] wouldn't be a replacement for (void) here.
So, if I value consistency and having-a-small-subset-of-C++-to-teach, and I
have to teach (void) here,[*] I don't see why I should teach a different
syntax anywhere else.
[* — Teach to library contributors and other advanced folks; obviously not
teach on Day 2 of the intro course. :)]
[** — Alternatively one could teach this cast-free version:
    for (int i = 0; i < n; ++i, void(), (update(n) [[discard]]))
but I don't think that's any easier to teach nor easier to read nor even
easier to write. Or of course one could stick to one's guns and move the
increment to the bottom line of the loop; but then one must also warn the
contributor not to use `continue`; that leads to a nice
structured-programming fixed-point but it may be unacceptable to some.]

IMO the paper should mention this use of comma, even if only to dismiss it
as "not relevant because this is not a place the compiler would warn
anyway" or "there are better ways to write this" or whatever. Just get the
whole question out of the way, one way or another.

In a C++-future project wouldn't it be nice™ to be able to have as
> coding policies 1) to forbid C-style casts (and especially those to
> void), and 2) require people to use [[discard("with reason")]] instead¹?
>

FWIW, I say no; that sounds like churn for churn's sake. For *me*, I would
particularly allow casts-to-void, because those have a long-standing
meaning blessed by tradition; and also casts-equivalent-to-static-cast
(which sadly would have to be enforced by clang-tidy, not by lint/grep);
but forbid casts-equivalent-to-reinterpret-or-const_cast.

–Arthur

Received on 2023-10-06 14:23:14