C++ Logo

std-proposals

Advanced search

Re: [std-proposals] A new C++ keyword: forget

From: Connor Song <perdixky_at_[hidden]>
Date: Wed, 12 Aug 2026 20:13:13 +0800
Hi all,

I wonder whether _ could cover much of this use case without introducing a
new redact construct.

My intuition is that _ already communicates something close to:

this object may need to exist, but its name is not intended to have a
stable identity that later code should remember.

That seems especially relevant to the cases where redact is useful only
because the object must remain alive while direct access to it should
effectively disappear.

For example, consider a borrowing wrapper:

Socket _ = connect();

TlsConnection secure(_);

// from here on, use only `secure`
secure.send(data);

The underlying Socket still has to remain alive because secure borrows it,
so introducing an inner scope and destroying it early would be wrong.

But giving it a normal name such as raw also advertises a stable access
path which later code can accidentally use:

Socket raw = connect();
TlsConnection secure(raw);

raw.send(data); // accidentally bypasses TLS

With _, the declaration itself already tells the reader that the underlying
socket has no meaningful long-term name.

I think this becomes more interesting if name-independent declarations
named _ are allowed to rebind _ within the same scope.

Conceptually, I have in mind a rule along the lines of:

Multiple name-independent declarations named _ may inhabit the same scope.
An id-expression _ denotes the most recently preceding such declaration.

There is one important additional rule I think would be needed:

The binding introduced by a new _ declaration becomes the current _ only
after its initializer has been evaluated.

That would make pipelines possible:

auto _ = receive();

auto _ = decrypt(_);

auto _ = authenticate(_);

process(_);

Here the _ in decrypt(_) refers to the result of receive(), while after
that declaration completes, _ refers to the result of decrypt().

Likewise, the _ in authenticate(_) refers to the decrypted value, and the
new binding becomes current only after initialization is complete.

In other words, this:

auto _ = parse(input);
auto _ = validate(_);
auto _ = normalize(_);
consume(_);

would naturally express a sequence in which each intermediate value is
intentionally anonymous and only the latest stage matters.

Importantly, I would not want rebinding _ to end the lifetime of the
previous object.

For example:

Socket _ = connect();
TlsConnection secure(_);

Widget _ = make_widget();

the original Socket object must still remain alive for as long as normal
C++ lifetime rules require, even though _ now denotes the Widget.

So this would affect name binding, not object lifetime.

That distinction seems useful to me:

   -

   a normal identifier gives an object a stable identity;
   -

   _ gives an object only a temporary handle;
   -

   introducing a new _ replaces that handle without destroying the previous
   object.

This also seems preferable to

Socket raw = connect();
TlsConnection secure(raw);

redact raw;

because with redact, the fact that raw is intended to be temporary is only
revealed later.

With

Socket _ = connect();

that intent is visible immediately at the declaration site.

So I wonder whether the problem is less about needing a way to revoke
ordinary names, and more about making name-independent _ useful as an
explicitly ephemeral binding.

Best,
Connor

Received on 2026-08-12 12:13:32