Date: Wed, 12 Aug 2026 12:45:19 +0200
I entirely agree that any changes have to be as unambiguous as possible.
But I disagree with the restrictions and limitations you want.
I think it is /fine/ that new objects are created with this shadowing:
int a = 1;
double a = a;
That should mean the same as :
int a = 1;
{
double a = a;
}
or
int a_1 = 1;
double a_2 = a_1;
I don't seem ambiguity or scope for misinterpretation.
Similarly :
typeA_t a;
typeA_t const a = a;
That's a creation of a new object "a", of type "typeA_t const",
initialised with the value of the old object "a". Simple and clear.
If you want a way to say that this is just a new name for the same old
object, perhaps "viewed" as a different type or differently qualified
type, then we have a way to do that too :
typeA_t a;
typeA_t const &a = a;
To my eyes, at least, these two examples above are clear. Writing
"typeA_t const a = a;" and expecting it to work as a reference, rather
than a new object, would be highly counter-intuitive.
My suggestions here are simply allowing the re-use of the existing
identifier, shadowing the previous one, without the source-code overhead
of adding a new block. I realise this is providing more than you were
originally asking for or suggesting.
David
On 12/08/2026 11:16, Tiago Freire wrote:
> I don't think that a new variable declaration should be allowed, it would be too confusing and ambiguous.
> Not only for the reasons we don't allow this today, but also as a consequence of the intended feature.
>
> The intention of the "redeclaration" feature is purely semantical in nature. We don't want any runtime effects out of the action of "redeclaring" a variable
> (with the exception of a potential address offset calculation in the case of inheritance or virtual inheritance, but let us ignore this case for now).
> No new objects should be created; no function or destructor/constructor should be called.
>
> Take for example the following code:
>
> int a = 1;
> double a = a;
>
> What does this mean? I would say the only thing it could mean is a cast from int to double and have the double shadow the int.
> Ok, now what about this?
>
> typeA_t a;
> typeA_t const a = a;
>
> Do I want to redeclare 'a' semantically? Or do I want to create a new object using a copy constructor passing in 'a' and have this new object shadow the original 'a'?
>
> We should opt for a way to express this idea without ambiguity. It must be done in a way as to make it clear that what we are expressing has only semantical consequences, and it cannot be anything else.
>
> Tiago
>
> -----Original Message-----
> From: David Brown <david.brown_at_[hidden]>
> Sent: Wednesday, August 12, 2026 09:52
> To: std-proposals_at_[hidden]
> Cc: Tiago Freire <tmiguelf_at_[hidden]>; David Brown <david.brown_at_[hidden]>
> Subject: Re: [std-proposals] A new C++ keyword: forget
>
> We could come a very long way with all this with three changes / additions to the language :
>
> 1. Allow a new variable declaration to shadow an exiting one, starting a new scope without having to open a new block. Thus :
>
> int a = 1;
> do_something(a);
> int a = 2;
> do_something_else(a);
> double a = 3;
> do_another_thing(a);
>
> would mean the same as :
>
> int a = 1;
> do_something(a);
> {
> int a = 2;
> do_something_else(a);
> {
> double a = 3;
> do_another_thing(a);
> }
> }
>
>
> 2. Allow declaring a variable of "void" type. Now "void a;" covers the OP's idea of "forget", since a variable of type "void" can't do much except have its address taken. Alternatively, we could have
>
> struct std::forget_t {};
>
> and then use "std::forget_t a;" to forget "a".
>
>
> 3. Keep the previous declaration "a" in scope while declaring the new "a". This is the difficult bit, because it changes existing behaviour.
> If this change can be achieved, then your "shadow(const) var;" becomes "const auto var = var;", and your "shadow(const A&) var;" becomes "const A& var = var;". To me, that syntax is a lot clearer.
>
> Most situations in which a declaration refers to the variable being declared use sizeof, since the value of the variable is not yet established and its use is UB (or erroneous behaviour). In C you have the common idiom :
>
> int * p = malloc(sizeof *p);
>
> Such code would have to keep its old effect (though it is not nearly as common in C++, for obvious reasons - including needing an extra cast).
> There is also the idiom of "int x = x;" as a way of disabling compiler warnings about use of "x" before initialisation.
>
> AFAIUI, what is currently not allowed in C++ - and therefore won't cause trouble with existing code - is referring to a type-deduced variable before initialisation. So "auto x = sizeof(x);" will not deduce "x" to be "size_t" - it is a constraint error. Thus "const auto var = var;" is currently invalid code, so this change would be backwards-compatible in any type-deduced context.
>
> That would not let you have the type-change, however - "const A& var = var;" does not involve type deduction. But you could write :
>
> const auto var = static_cast<A&>(var);
>
> The idea needs more thought to have a way that allows this change without affecting existing code and where it is clear to the programmer when the new declaration is referring to the previous declaration, and when it is referring to the current one.
>
> But I know I'd find these features convenient in my own code, if they were allowed.
>
> David
>
>
>
> On 11/08/2026 21:28, Tiago Freire via Std-Proposals wrote:
>> Hum, this could be useful if combined with other features.
>> Something that I want is to be able to make const a variable that is
>> originally not declared const.
>>
>> Maybe we could have a "shadowing" specifier, that could do that.
>>
>> Like
>> shadow(const) var; //makes var const for the remainder of the scope.
>> shadow(void) var; //makes var inaccessible
>>
>> I can also see the feature being used as.
>>
>> class A{};
>> class B: public A{};
>> B var;
>>
>> shadow(const A&) var; //var is still an object of type B but only
>> accessible as an object of parent type A.
>>
>> I'm not so sure about this last one.
>>
>>
>> ----------------------------------------------------------------------
>> --
>> *From:* Std-Proposals <std-proposals-bounces_at_[hidden]> on
>> behalf of Ville Voutilainen via Std-Proposals
>> <std-proposals_at_[hidden]>
>> *Sent:* Tuesday, August 11, 2026 9:13:23 PM
>> *To:* std-proposals_at_[hidden] <std-proposals_at_[hidden]>
>> *Cc:* Ville Voutilainen <ville.voutilainen_at_[hidden]>
>> *Subject:* Re: [std-proposals] A new C++ keyword: forget
>>
>> On Tue, 11 Aug 2026 at 22:11, Henry Skoglund via Std-Proposals
>> <std-proposals_at_[hidden]> wrote:
>> >
>> > On 2026-08-11 21:05, Simon Schröder wrote:
>> > > This reminds me (in case you are continuing with the proposal):
>> You should discuss if once a variable has been poisoned, if the same
>> name can be reused for a different variable.
>> > Hi, once poisoned I think it should not be allowed to be reused. I.e.
>> > issue a compiler error like:
>> > double raw;
>> > forget raw;
>> > int raw; // <--- error: raw is forgotten and cannot be
>> resurrected
>>
>> Exactly. Make name lookup still find the name, but make it an error to
>> find a poisoned name.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals <https://
>> lists.isocpp.org/mailman/listinfo.cgi/std-proposals>
>>
>>
>
But I disagree with the restrictions and limitations you want.
I think it is /fine/ that new objects are created with this shadowing:
int a = 1;
double a = a;
That should mean the same as :
int a = 1;
{
double a = a;
}
or
int a_1 = 1;
double a_2 = a_1;
I don't seem ambiguity or scope for misinterpretation.
Similarly :
typeA_t a;
typeA_t const a = a;
That's a creation of a new object "a", of type "typeA_t const",
initialised with the value of the old object "a". Simple and clear.
If you want a way to say that this is just a new name for the same old
object, perhaps "viewed" as a different type or differently qualified
type, then we have a way to do that too :
typeA_t a;
typeA_t const &a = a;
To my eyes, at least, these two examples above are clear. Writing
"typeA_t const a = a;" and expecting it to work as a reference, rather
than a new object, would be highly counter-intuitive.
My suggestions here are simply allowing the re-use of the existing
identifier, shadowing the previous one, without the source-code overhead
of adding a new block. I realise this is providing more than you were
originally asking for or suggesting.
David
On 12/08/2026 11:16, Tiago Freire wrote:
> I don't think that a new variable declaration should be allowed, it would be too confusing and ambiguous.
> Not only for the reasons we don't allow this today, but also as a consequence of the intended feature.
>
> The intention of the "redeclaration" feature is purely semantical in nature. We don't want any runtime effects out of the action of "redeclaring" a variable
> (with the exception of a potential address offset calculation in the case of inheritance or virtual inheritance, but let us ignore this case for now).
> No new objects should be created; no function or destructor/constructor should be called.
>
> Take for example the following code:
>
> int a = 1;
> double a = a;
>
> What does this mean? I would say the only thing it could mean is a cast from int to double and have the double shadow the int.
> Ok, now what about this?
>
> typeA_t a;
> typeA_t const a = a;
>
> Do I want to redeclare 'a' semantically? Or do I want to create a new object using a copy constructor passing in 'a' and have this new object shadow the original 'a'?
>
> We should opt for a way to express this idea without ambiguity. It must be done in a way as to make it clear that what we are expressing has only semantical consequences, and it cannot be anything else.
>
> Tiago
>
> -----Original Message-----
> From: David Brown <david.brown_at_[hidden]>
> Sent: Wednesday, August 12, 2026 09:52
> To: std-proposals_at_[hidden]
> Cc: Tiago Freire <tmiguelf_at_[hidden]>; David Brown <david.brown_at_[hidden]>
> Subject: Re: [std-proposals] A new C++ keyword: forget
>
> We could come a very long way with all this with three changes / additions to the language :
>
> 1. Allow a new variable declaration to shadow an exiting one, starting a new scope without having to open a new block. Thus :
>
> int a = 1;
> do_something(a);
> int a = 2;
> do_something_else(a);
> double a = 3;
> do_another_thing(a);
>
> would mean the same as :
>
> int a = 1;
> do_something(a);
> {
> int a = 2;
> do_something_else(a);
> {
> double a = 3;
> do_another_thing(a);
> }
> }
>
>
> 2. Allow declaring a variable of "void" type. Now "void a;" covers the OP's idea of "forget", since a variable of type "void" can't do much except have its address taken. Alternatively, we could have
>
> struct std::forget_t {};
>
> and then use "std::forget_t a;" to forget "a".
>
>
> 3. Keep the previous declaration "a" in scope while declaring the new "a". This is the difficult bit, because it changes existing behaviour.
> If this change can be achieved, then your "shadow(const) var;" becomes "const auto var = var;", and your "shadow(const A&) var;" becomes "const A& var = var;". To me, that syntax is a lot clearer.
>
> Most situations in which a declaration refers to the variable being declared use sizeof, since the value of the variable is not yet established and its use is UB (or erroneous behaviour). In C you have the common idiom :
>
> int * p = malloc(sizeof *p);
>
> Such code would have to keep its old effect (though it is not nearly as common in C++, for obvious reasons - including needing an extra cast).
> There is also the idiom of "int x = x;" as a way of disabling compiler warnings about use of "x" before initialisation.
>
> AFAIUI, what is currently not allowed in C++ - and therefore won't cause trouble with existing code - is referring to a type-deduced variable before initialisation. So "auto x = sizeof(x);" will not deduce "x" to be "size_t" - it is a constraint error. Thus "const auto var = var;" is currently invalid code, so this change would be backwards-compatible in any type-deduced context.
>
> That would not let you have the type-change, however - "const A& var = var;" does not involve type deduction. But you could write :
>
> const auto var = static_cast<A&>(var);
>
> The idea needs more thought to have a way that allows this change without affecting existing code and where it is clear to the programmer when the new declaration is referring to the previous declaration, and when it is referring to the current one.
>
> But I know I'd find these features convenient in my own code, if they were allowed.
>
> David
>
>
>
> On 11/08/2026 21:28, Tiago Freire via Std-Proposals wrote:
>> Hum, this could be useful if combined with other features.
>> Something that I want is to be able to make const a variable that is
>> originally not declared const.
>>
>> Maybe we could have a "shadowing" specifier, that could do that.
>>
>> Like
>> shadow(const) var; //makes var const for the remainder of the scope.
>> shadow(void) var; //makes var inaccessible
>>
>> I can also see the feature being used as.
>>
>> class A{};
>> class B: public A{};
>> B var;
>>
>> shadow(const A&) var; //var is still an object of type B but only
>> accessible as an object of parent type A.
>>
>> I'm not so sure about this last one.
>>
>>
>> ----------------------------------------------------------------------
>> --
>> *From:* Std-Proposals <std-proposals-bounces_at_[hidden]> on
>> behalf of Ville Voutilainen via Std-Proposals
>> <std-proposals_at_[hidden]>
>> *Sent:* Tuesday, August 11, 2026 9:13:23 PM
>> *To:* std-proposals_at_[hidden] <std-proposals_at_[hidden]>
>> *Cc:* Ville Voutilainen <ville.voutilainen_at_[hidden]>
>> *Subject:* Re: [std-proposals] A new C++ keyword: forget
>>
>> On Tue, 11 Aug 2026 at 22:11, Henry Skoglund via Std-Proposals
>> <std-proposals_at_[hidden]> wrote:
>> >
>> > On 2026-08-11 21:05, Simon Schröder wrote:
>> > > This reminds me (in case you are continuing with the proposal):
>> You should discuss if once a variable has been poisoned, if the same
>> name can be reused for a different variable.
>> > Hi, once poisoned I think it should not be allowed to be reused. I.e.
>> > issue a compiler error like:
>> > double raw;
>> > forget raw;
>> > int raw; // <--- error: raw is forgotten and cannot be
>> resurrected
>>
>> Exactly. Make name lookup still find the name, but make it an error to
>> find a poisoned name.
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals <https://
>> lists.isocpp.org/mailman/listinfo.cgi/std-proposals>
>>
>>
>
Received on 2026-08-12 10:45:26
