This variable should not be named: an identifier (not) to remember

490 views
Skip to first unread message

Alberto Barbati

unread,
Mar 27, 2017, 4:27:11 PM3/27/17
to ISO C++ Standard - Future Proposals
Hello,

this is a draft for a proposal to add a special meaning to the identifier __ (double underscore) so that it can be used (even repeatedly in the same lexical scope) for all variables whose name is not important and that is no longer needed after declaration. The draft includes a few examples.

Is there any interest in this?

Thanks in advance,

Alberto

This Variable Should Not Be Named.pdf

Christopher Di Bella

unread,
Mar 27, 2017, 4:51:23 PM3/27/17
to ISO C++ Standard - Future Proposals

Hi,

Thanks for taking the time out to write this! It seems like there is motivation, but I can't quite place my finger on it. If a variable isn't going to be used again, and can't be referenced, what are the benefits of its persistence have over `Foo{bar};`?

Cheers,

Chris


--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/985b9b2a-c734-45eb-95f4-db4dc0d309a1%40isocpp.org.

Ville Voutilainen

unread,
Mar 27, 2017, 5:02:38 PM3/27/17
to ISO C++ Standard - Future Proposals

Thiago Macieira

unread,
Mar 27, 2017, 5:30:24 PM3/27/17
to std-pr...@isocpp.org
Just remember that there are already existing codebases using __ as identifier
or macro names.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center

Jeffrey Yasskin

unread,
Mar 27, 2017, 6:17:20 PM3/27/17
to std-pr...@isocpp.org
On Mon, Mar 27, 2017 at 2:30 PM, Thiago Macieira <thi...@macieira.org> wrote:
On segunda-feira, 27 de março de 2017 13:27:11 PDT Alberto Barbati wrote:
> Hello,
>
> this is a draft for a proposal to add a special meaning to the identifier
> __ (double underscore) so that it can be used (even repeatedly in the same
> lexical scope) for all variables whose name is not important and that is no
> longer needed after declaration. The draft includes a few examples.
>
> Is there any interest in this?

Just remember that there are already existing codebases using __ as identifier
or macro names.

They're not allowed. "_" is ok outside of the global namespace, but "__" is reserved by [lex.name].

Jeffrey

Thiago Macieira

unread,
Mar 28, 2017, 1:39:30 AM3/28/17
to std-pr...@isocpp.org
On segunda-feira, 27 de março de 2017 15:16:58 PDT 'Jeffrey Yasskin' via ISO C
++ Standard - Future Proposals wrote:
> > Just remember that there are already existing codebases using __ as
> > identifier
> > or macro names.
>
> They're not allowed. "_" is ok outside of the global namespace, but "__" is
> reserved by [lex.name].

I know it is.

And yet it's in use.
https://github.com/v8/v8/blob/master/src/x64/codegen-x64.cc#L33

Alberto Barbati

unread,
Mar 28, 2017, 2:18:46 AM3/28/17
to std-pr...@isocpp.org
Hi Chris,

Even if it cannot be referenced again, a __ variable is still a variable and therefore it ends its lifetime at the end of the lexical scope. Its destructor is therefore called when the scope is exited either normally or exceptionally and no sooner. This is the main point of the RAII idiom. On the other hand, `Foo{bar};` creates a temporary object that is immediately destroyed at the end of the statement.

Cheers,

Alberto
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/BTVwFqDkhXk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Alberto Barbati

unread,
Mar 28, 2017, 2:23:11 AM3/28/17
to std-pr...@isocpp.org
Hi Ville,

Thanks a lot for the pointer! Whoa! This issue is ancient... I'll make sure the next version will have a reference to it and address the concerns it raises.

Cheers,

Alberto
> --
> You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
> To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/BTVwFqDkhXk/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.
> To post to this group, send email to std-pr...@isocpp.org.
> To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/CAFk2RUZ3%2Byru%2BcYSEtxJ1TbZuyWp71gpCGoq%3DWE_8EAE%3D%2Bh%3D2g%40mail.gmail.com.

Alberto Barbati

unread,
Mar 28, 2017, 2:48:00 AM3/28/17
to std-pr...@isocpp.org

> Il giorno 28 mar 2017, alle ore 07:39, Thiago Macieira <thi...@macieira.org> ha scritto:
>
> On segunda-feira, 27 de março de 2017 15:16:58 PDT 'Jeffrey Yasskin' via ISO C
> ++ Standard - Future Proposals wrote:
>>> Just remember that there are already existing codebases using __ as
>>> identifier
>>> or macro names.
>>
>> They're not allowed. "_" is ok outside of the global namespace, but "__" is
>> reserved by [lex.name].
>
> I know it is.
>
> And yet it's in use.
> https://github.com/v8/v8/blob/master/src/x64/codegen-x64.cc#L33

Thanks Thiago for the pointer. According to my (possibly incorrect) interpretation this code raises undefined behavior because __ is reserved "for any use", which I would expect includes the use as a macro name. I may be wrong, but I'd expect little sympathy in the committee about potentially breaking it. By the way, this code might possibly not break, because they were clever to put #undefs in it. Incidentally, the code would indeed break if we defined __ to be a macro...

Cheers,

Alberto

Thiago Macieira

unread,
Mar 28, 2017, 3:04:16 AM3/28/17
to std-pr...@isocpp.org
Em segunda-feira, 27 de março de 2017, às 23:47:55 PDT, Alberto Barbati
escreveu:
> > And yet it's in use.
> > https://github.com/v8/v8/blob/master/src/x64/codegen-x64.cc#L33
>
> Thanks Thiago for the pointer. According to my (possibly incorrect)
> interpretation this code raises undefined behavior because __ is reserved
> "for any use", which I would expect includes the use as a macro name. I may
> be wrong, but I'd expect little sympathy in the committee about potentially
> breaking it. By the way, this code might possibly not break, because they
> were clever to put #undefs in it. Incidentally, the code would indeed break
> if we defined __ to be a macro...

Right. We can say it's V8's own fault for using a reserved identifier. It's
like when Qt (qlalr) had an identifier called _Nullable, but that got
repurposed by a recent Clang change.

I'm just saying it's known to be in use in a fairly major project. You know,
the one that is behind Node.js and a whole ecosystem. The argument in the
paper that says it's little used is incorrect: it's not like pre-C++11 "auto",
which had exactly one use in the entire Microsoft source code.

I guess we could convince GCC and Clang to print a warning about it if it
looks like this is going forward, so the V8 developers start fixing it. Maybe
we'll get some of these fixed too:

http://lxr.free-electrons.com/source/include/linux/compiler.h#L115
http://lxr.free-electrons.com/source/include/asm-generic/fixmap.h#L73

Viacheslav Usov

unread,
Mar 28, 2017, 5:08:20 AM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 8:22 AM, Alberto Barbati <alberto...@gmail.com> wrote:

> Thanks a lot for the pointer! Whoa! This issue is ancient... I'll make sure the next version will have a reference to it and address the concerns it raises.

This keeps coming back to this forum. For example, this: https://groups.google.com/a/isocpp.org/d/msg/std-proposals/ioi76TkG6g4/G8WC37LVAAAJ

My take on this is that we should have an operator or a keyword that extends the lifetime of a temporary, as discussed here https://groups.google.com/a/isocpp.org/d/msg/std-proposals/ioi76TkG6g4/bdUinF-3AQAJ and subsequent posts, notably this https://groups.google.com/a/isocpp.org/d/msg/std-proposals/ioi76TkG6g4/bdUinF-3AQAJ and this https://groups.google.com/a/isocpp.org/d/msg/std-proposals/ioi76TkG6g4/5JrGmugAAgAJ

Cheers,
V.

Alberto Barbati

unread,
Mar 28, 2017, 5:09:56 AM3/28/17
to std-pr...@isocpp.org
2017-03-28 9:04 GMT+02:00 Thiago Macieira <thi...@macieira.org>:
Em segunda-feira, 27 de março de 2017, às 23:47:55 PDT, Alberto Barbati
escreveu:
> > And yet it's in use.
> > https://github.com/v8/v8/blob/master/src/x64/codegen-x64.cc#L33
>
> Thanks Thiago for the pointer. According to my (possibly incorrect)
> interpretation this code raises undefined behavior because __ is reserved
> "for any use", which I would expect includes the use as a macro name. I may
> be wrong, but I'd expect little sympathy in the committee about potentially
> breaking it. By the way, this code might possibly not break, because they
> were clever to put #undefs in it. Incidentally, the code would indeed break
> if we defined __ to be a macro...

Right. We can say it's V8's own fault for using a reserved identifier. It's
like when Qt (qlalr) had an identifier called _Nullable, but that got
repurposed by a recent Clang change.

In this particular instance, V8's programmer could and probably should have used a non-reserved name (for example "m_" would have been a better choice regardless). Even the choice of _Nullable was ill-conceived, since identifiers beginning with an underscore and an uppercase letter are also reserved.
 
I'm just saying it's known to be in use in a fairly major project. You know,
the one that is behind Node.js and a whole ecosystem. The argument in the
paper that says it's little used is incorrect: it's not like pre-C++11 "auto",
which had exactly one use in the entire Microsoft source code.

I said that it's little used in the two librariesI have checked (VS2015 and libc++). For user code such as this, all I said is that "the proposal should not break code", which is correct: the identifier __ should not have been used in the first place, so this is a case of code that someone might say "deserves to be broken".
 
I guess we could convince GCC and Clang to print a warning about it if it
looks like this is going forward, so the V8 developers start fixing it. Maybe
we'll get some of these fixed too:

http://lxr.free-electrons.com/source/include/linux/compiler.h#L115
http://lxr.free-electrons.com/source/include/asm-generic/fixmap.h#L73

The first one, that #defines "if", is particularly disturbing.

Cheers,

Alberto

Alberto Barbati

unread,
Mar 28, 2017, 5:23:57 AM3/28/17
to std-pr...@isocpp.org
Thanks for taking the time to collect these links, I will have a look at them.

As for having a keyword to extend the lifetime of a temporary, there is a formal proposal for that (http://wg21.link/p0577), which I referenced in my draft. However I believe P0577 does not address the issue of decomposition declarations and has a greater syntactic cost (it re-uses the "register" keyword). It's true that P0577 provides additional use cases, though, but I am yet to be convinced of their usefulness.

Alberto

Matthew Woehlke

unread,
Mar 28, 2017, 9:55:54 AM3/28/17
to std-pr...@isocpp.org
On 2017-03-28 05:23, Alberto Barbati wrote:
> 2017-03-28 11:08 GMT+02:00 Viacheslav Usov <via....@gmail.com>:
>> This keeps coming back to this forum. For example, this:
>> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/ioi76TkG6g4/
>> G8WC37LVAAAJ
>>
>> My take on this is that we should have an operator or a keyword that
>> extends the lifetime of a temporary, as discussed here
>> https://groups.google.com/a/isocpp.org/d/msg/std-
>> proposals/ioi76TkG6g4/bdUinF-3AQAJ and subsequent posts, notably this
>> https://groups.google.com/a/isocpp.org/d/msg/std-
>> proposals/ioi76TkG6g4/bdUinF-3AQAJ and this https://groups.google.
>> com/a/isocpp.org/d/msg/std-proposals/ioi76TkG6g4/5JrGmugAAgAJ
>
> Thanks for taking the time to collect these links, I will have a look at
> them.
>
> As for having a keyword to extend the lifetime of a temporary, there is a
> formal proposal for that (http://wg21.link/p0577), which I referenced in my
> draft. However I believe P0577 does not address the issue of decomposition
> declarations and has a greater syntactic cost (it re-uses the "register"
> keyword). It's true that P0577 provides additional use cases, though, but I
> am yet to be convinced of their usefulness.

The main use case for `register` as lifetime extension is that you can
use it like:

for (auto item : add_const(register make_list()))

...where you would otherwise need an additional declaration. The
decomposition case I think would be best solved by allowing empty and
nested declarations. See
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/gg3_eUhCuqo/HcippDFiBgAJ
and following posts in the thread. This would let you write:

auto [] = get_lock(); // no name
auto [x, [], y] = get_tuple(); // middle element is unnamed
auto [x, [a, b], y] = get_tuple(); // nested decomposition

Both solve the simple case, but both also have additional but
non-overlapping usefulness. I'm inclined to think that both are useful.

--
Matthew

Viacheslav Usov

unread,
Mar 28, 2017, 10:22:15 AM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 3:55 PM, Matthew Woehlke <mwoehlk...@gmail.com> wrote:

> Both solve the simple case, but both also have additional but non-overlapping usefulness. I'm inclined to think that both are useful.

The usefulness is hard to deny, but I have another consideration. Anonymous lifetime extension is something that we have wanted for years, or indeed, for decades. Anonymous decomposition, on the other hand, would be very new, because the feature it depends on is not even officially standardised yet. I, for one, do not yet have an intuitive feeling how I would like that to work.

Also of note is that the authors of the structured bindings proposal did consider that (P0144R2, 3.8):

We think the answer should be “not yet.” This is not motivated by use cases (silencing compiler warnings is a motivation, but it is not a use case per se), and is best left until we can revisit this in the context of a more general pattern matching proposal where this should fall out as a special case. 

(end)

I think that still stands.

Cheers,
V.

Thiago Macieira

unread,
Mar 28, 2017, 12:16:48 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 02:09:54 PDT Alberto Barbati wrote:
> In this particular instance, V8's programmer could and probably should have
> used a non-reserved name (for example "m_" would have been a better choice
> regardless). Even the choice of _Nullable was ill-conceived, since
> identifiers beginning with an underscore and an uppercase letter are also
> reserved.

The reason for __ is that it looks unintrusive, which allows for code
generation in a way that is easy to read:

// Fetch the instance type of the receiver into result register.
__ movp(result, FieldOperand(string, HeapObject::kMapOffset));
__ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));

// We need special handling for indirect strings.
Label check_sequential;
__ testb(result, Immediate(kIsIndirectStringMask));
__ j(zero, &check_sequential, Label::kNear);

Zhihao Yuan

unread,
Mar 28, 2017, 12:27:38 PM3/28/17
to std-pr...@isocpp.org

On Tue, Mar 28, 2017 at 4:23 AM, Alberto Barbati <alberto...@gmail.com> wrote:
However I believe P0577 does not address the issue of decomposition declaration

Because these two "use cases" imply different semantics.
When you write

  auto __ = lock_guard(m);

here you mean to *preserve* the result object, but when
you write

  auto [__, a] = get_tuple(...);

you mean to *ignore* a part of the result object, so
physically, just like std::ignore, I don't expect __ here
to issue a call to get(obj), nor an access to a subobject.
I don't think the *preserving* semantics can fulfill the
*ignoring* demand.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________

Brittany Friedman

unread,
Mar 28, 2017, 12:34:29 PM3/28/17
to std-pr...@isocpp.org

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.



Instead of __, I'd propose using ?. For example auto ? = scope_guard{...}. ? isn't allowed in identifiers so it shouldn't conflict with existing nonconformant code. ? is also shorter :)

Thiago Macieira

unread,
Mar 28, 2017, 12:43:32 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 09:27:34 PDT Zhihao Yuan wrote:
> here you mean to *preserve* the result object, but when
> you write
>
> auto [__, a] = get_tuple(...);
>
> you mean to *ignore* a part of the result object, so
> physically, just like std::ignore, I don't expect __ here
> to issue a call to get(obj), nor an access to a subobject.
> I don't think the *preserving* semantics can fulfill the
> *ignoring* demand.

It has no difference, because the structured binding is actually a *binding*,
so there's difference to object creation or retention. The result from
get_tuple is assigned to an anonymous object and all its members are retained.
Then it's decomposed into two elements: an anonymous one (can't be accessed)
and a.

Zhihao Yuan

unread,
Mar 28, 2017, 12:53:55 PM3/28/17
to std-pr...@isocpp.org

On Tue, Mar 28, 2017 at 11:43 AM, Thiago Macieira <thi...@macieira.org> wrote:
just like std::ignore, I don't expect __ here
> to issue a call to get(obj), nor an access to a subobject.
> I don't think the *preserving* semantics can fulfill the
> *ignoring* demand.

It has no difference, because the structured binding is actually a *binding*,
so there's difference to object creation or retention. The result from
get_tuple is assigned to an anonymous object and all its members are retained.
Then it's decomposed into two elements: an anonymous one (can't be accessed)
and a.

Whether a call to get<0>(anon) being made
certainly has difference, because it can have
observable effect.  And, just like I showed
in a previous discussion, the purpose of the
anonymous object is for decomposition.  If
nothing is decomposition it, it needs not to be
created, therefore

  auto [__, __] = get_tuple(...);

should be physically equivalent to

  get_tuple(...);

thus, the result object is dropped on the floor.

Thiago Macieira

unread,
Mar 28, 2017, 1:03:48 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 09:53:51 PDT Zhihao Yuan wrote:
> auto [__, __] = get_tuple(...);
>
> should be physically equivalent to
>
> get_tuple(...);
>
> thus, the result object is dropped on the floor.

This should be equivalent to:

auto __ = get_tuple(...);

Viacheslav Usov

unread,
Mar 28, 2017, 1:14:51 PM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 7:03 PM, Thiago Macieira <thi...@macieira.org> wrote:

> This should be equivalent to:

>        auto __ = get_tuple(...);

Which it is, if auto __ means either "DO retain the object" or "do NOT retain the object" 

Cheers,
V.

Nicol Bolas

unread,
Mar 28, 2017, 1:18:42 PM3/28/17
to ISO C++ Standard - Future Proposals, z...@miator.net


On Tuesday, March 28, 2017 at 12:53:55 PM UTC-4, Zhihao Yuan wrote:

On Tue, Mar 28, 2017 at 11:43 AM, Thiago Macieira <thi...@macieira.org> wrote:
just like std::ignore, I don't expect __ here
> to issue a call to get(obj), nor an access to a subobject.
> I don't think the *preserving* semantics can fulfill the
> *ignoring* demand.

It has no difference, because the structured binding is actually a *binding*,
so there's difference to object creation or retention. The result from
get_tuple is assigned to an anonymous object and all its members are retained.
Then it's decomposed into two elements: an anonymous one (can't be accessed)
and a.

Whether a call to get<0>(anon) being made
certainly has difference, because it can have
observable effect.  And, just like I showed
in a previous discussion, the purpose of the
anonymous object is for decomposition.  If
nothing is decomposition it, it needs not to be
created, therefore

  auto [__, __] = get_tuple(...);

should be physically equivalent to

  get_tuple(...);

thus, the result object is dropped on the floor.

No, it should not. It should create a hidden variable, initialize it with the return value of the expression, then extract nothing from it. The hidden variable will always be destroyed at the end of scope.

The behavior of `auto [name, __]` should not be substantially different from that of `auto [__, __]`. What you're saying would violate that.

Matt Calabrese

unread,
Mar 28, 2017, 1:21:46 PM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 1:39 AM, Thiago Macieira <thi...@macieira.org> wrote:
On segunda-feira, 27 de março de 2017 15:16:58 PDT 'Jeffrey Yasskin' via ISO C
++ Standard - Future Proposals wrote:
> > Just remember that there are already existing codebases using __ as
> > identifier
> > or macro names.
>
> They're not allowed. "_" is ok outside of the global namespace, but "__" is
> reserved by [lex.name].

I know it is.

And yet it's in use.
https://github.com/v8/v8/blob/master/src/x64/codegen-x64.cc#L33

If we are afraid to break people who use explicitly reserved identifiers, then I think we'd be making a huge mistake. I agree that we should always minimize breaking people when it makes sense and I know that people draw the line at different places, but we should at least be able to make use of an identifier that has been reserved since the initial standard.

Thiago Macieira

unread,
Mar 28, 2017, 1:29:46 PM3/28/17
to std-pr...@isocpp.org
As proposed by the OP: exactly as that declaration would do today, except that
you can't access it anymore.

Matthew Woehlke

unread,
Mar 28, 2017, 1:29:57 PM3/28/17
to std-pr...@isocpp.org
On 2017-03-28 13:03, Thiago Macieira wrote:
> On terça-feira, 28 de março de 2017 09:53:51 PDT Zhihao Yuan wrote:
>> auto [__, __] = get_tuple(...);
>>
>> should be physically equivalent to
>>
>> get_tuple(...);
>>
>> thus, the result object is dropped on the floor.
>
> This should be equivalent to:
>
> auto __ = get_tuple(...);

I would argue it should be equivalent to:

auto __magic__ = get_tuple(...); // note: same as today
auto __ = get<0>(__magic__);
auto __ = get<1>(__magic__);

...so that in case of side effects, there is no observable behavior
difference. (The compiler is free to elide bits of the above if there
are provably no side effects.)

This almost makes me think we need "unnamed" and "ignored" to be
implemented separately :'(...

--
Matthew

Nicol Bolas

unread,
Mar 28, 2017, 1:31:27 PM3/28/17
to ISO C++ Standard - Future Proposals

I have to agree with that. This is literally the whole point of reserving identifiers: so that we can use them later. It's not like adding a keyword, where we need to study the impact of making a change so as to minimize breakage.

If someone was using a reserved identifier (outside of a standard library implementation), their code is wrong. We told them to stay out of this area, and they didn't. Their code breaking is not our fault, nor is it on us to stay out of their way.

Now, one thing that's important in this regard is that we should do a study on the impact of this change on standard library implementations. Since we would obviously be taking away one of their identifiers.

Nicol Bolas

unread,
Mar 28, 2017, 1:39:12 PM3/28/17
to ISO C++ Standard - Future Proposals

The question is this: will people actually want side effects of ignored parameters? Or more to the point, why exactly would you want those side effects?

I can't think of a case of a type that is decomposable where the decomposition `get` function has side effects. Well, with one exception: variant types. And the side effect there is that you get a thrown exception.

So it seems to me that if I have a variant, and I do:

auto [__, name] = expr;

I clearly don't want the side effect of calling `get<0>`. I'm declaring very clearly that this variant is in state 1, and if it isn't, then throw.

So under what circumstances would a user want the side effect of `get` but not the name? We shouldn't add such a feature based on whether someone could use it. We should add the feature because someone has a genuine need to use it.

Viacheslav Usov

unread,
Mar 28, 2017, 1:41:34 PM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 7:29 PM, Thiago Macieira <thi...@macieira.org> wrote:

> As proposed by the OP: exactly as that declaration would do today

Which is UB.

Cheers,
V.

Matthew Woehlke

unread,
Mar 28, 2017, 1:51:51 PM3/28/17
to std-pr...@isocpp.org
On 2017-03-28 13:39, Nicol Bolas wrote:
> On Tuesday, March 28, 2017 at 1:29:57 PM UTC-4, Matthew Woehlke wrote:
>> On 2017-03-28 13:03, Thiago Macieira wrote:
>>> On terça-feira, 28 de março de 2017 09:53:51 PDT Zhihao Yuan wrote:
>>>> auto [__, __] = get_tuple(...);
>>>>
>>>> should be physically equivalent to
>>>>
>>>> get_tuple(...);
>>>>
>>>> thus, the result object is dropped on the floor.
>>>
>>> This should be equivalent to:
>>>
>>> auto __ = get_tuple(...);
>>
>> I would argue it should be equivalent to:
>>
>> auto __magic__ = get_tuple(...); // note: same as today
>> auto __ = get<0>(__magic__);
>> auto __ = get<1>(__magic__);
>
> The question is this: will people actually want side effects of ignored
> parameters? Or more to the point, why exactly would you want those side
> effects?

Consistency?

// Same? Uh... no?
auto __ = expr;
auto [__] = expr;

// Same? I hope so?
auto [__] = expr;
auto x = expr; auto __ = get<0>(x);

// Same? Better be!
auto [y] = expr;
auto x = expr; auto y = get<0>(x);

--
Matthew

Thiago Macieira

unread,
Mar 28, 2017, 1:52:22 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 09:53:51 PDT Zhihao Yuan wrote:
> Whether a call to get<0>(anon) being made
> certainly has difference, because it can have
> observable effect.

It does not, so it cannot have an observable effect.

Thiago Macieira

unread,
Mar 28, 2017, 1:54:04 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 10:31:27 PDT Nicol Bolas wrote:
> If someone was using a reserved identifier (outside of a standard library
> implementation), their code is wrong. We told them to stay out of this
> area, and they didn't. Their code breaking is not our fault, nor is it on
> us to stay out of their way.
>
> Now, one thing that's important in this regard is that we should do a study
> on the impact of this change on standard library implementations. Since we
> would obviously be taking away one of their identifiers.

I'm not saying we should avoid __.

I'm saying that the paper needs to be updated to indicate that the reserved
identifier is used and therefore we know we will cause breakage, regardless of
who is to blame.

Alberto Barbati

unread,
Mar 28, 2017, 4:27:30 PM3/28/17
to std-pr...@isocpp.org

Il giorno 28 mar 2017, alle ore 18:16, Thiago Macieira <thi...@macieira.org> ha scritto:

On terça-feira, 28 de março de 2017 02:09:54 PDT Alberto Barbati wrote:
In this particular instance, V8's programmer could and probably should have
used a non-reserved name (for example "m_" would have been a better choice
regardless). Even the choice of _Nullable was ill-conceived, since
identifiers beginning with an underscore and an uppercase letter are also
reserved.

The reason for __ is that it looks unintrusive, which allows for code
generation in a way that is easy to read:

 // Fetch the instance type of the receiver into result register.
 __ movp(result, FieldOperand(string, HeapObject::kMapOffset));
 __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));

I don't see it much easier to read than:

    m_ movp(result, FieldOperand(string, HeapObject::kMapOffset));
    m_ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));

especially when the macro m_ expands to some variation of "masm". Just my opinion.

A.

Alberto Barbati

unread,
Mar 28, 2017, 4:45:48 PM3/28/17
to std-pr...@isocpp.org

Il giorno 28 mar 2017, alle ore 18:27, Zhihao Yuan <z...@miator.net> ha scritto:


On Tue, Mar 28, 2017 at 4:23 AM, Alberto Barbati <alberto...@gmail.com> wrote:
However I believe P0577 does not address the issue of decomposition declaration

Because these two "use cases" imply different semantics.
When you write

  auto __ = lock_guard(m);

here you mean to *preserve* the result object, but when
you write

  auto [__, a] = get_tuple(...);

you mean to *ignore* a part of the result object, so
physically, just like std::ignore, I don't expect __ here
to issue a call to get(obj), nor an access to a subobject.
I don't think the *preserving* semantics can fulfill the
*ignoring* demand.

I see it differently. For me, those two are instances of the same use case: "I don't care about the name, since I don't need to refer to this lvalue anymore". In the first case we are not actually "preserving" anything, since we are declaring an object whose lifetime would end at the end of the lexical scope regardless of its name. Similarly in the second case, with the only difference that the name would be bound to a reference to a subobject of an object whose scope is defined irrespective of the binding. In this case the compiler can and probably would omit the binding without observable effects.

Cheers,

Alberto

Alberto Barbati

unread,
Mar 28, 2017, 4:50:17 PM3/28/17
to std-pr...@isocpp.org

> Il giorno 28 mar 2017, alle ore 19:29, Thiago Macieira <thi...@macieira.org> ha scritto:
>
>> On terça-feira, 28 de março de 2017 10:14:49 PDT Viacheslav Usov wrote:
>> On Tue, Mar 28, 2017 at 7:03 PM, Thiago Macieira <thi...@macieira.org>
>>
>> wrote:
>>> This should be equivalent to:
>>> auto __ = get_tuple(...);
>>
>> Which it is, if auto __ means either "DO retain the object" or "do NOT
>> retain the object"
>
> As proposed by the OP: exactly as that declaration would do today, except that
> you can't access it anymore.

Precisely. There's no "retain" or "not retain" added semantic, as I explained in another post.

Alberto

Alberto Barbati

unread,
Mar 28, 2017, 4:53:22 PM3/28/17
to std-pr...@isocpp.org
Care to explain? I can't see UB there.

Cheers,

Alberto

Viacheslav Usov

unread,
Mar 28, 2017, 5:09:32 PM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 10:53 PM, Alberto Barbati <alberto...@gmail.com> wrote:

> Care to explain? I can't see UB there.

[lex.name]/3 "In addition, some identifiers are reserved for use by C++ implementations and shall not be used otherwise; no diagnostic is required."

No behavior is imposed by the International Standard, hence [defns.undefined] applies.

Cheers,
V.

Alberto Barbati

unread,
Mar 28, 2017, 5:13:18 PM3/28/17
to std-pr...@isocpp.org


> Il giorno 28 mar 2017, alle ore 19:51, Matthew Woehlke <mwoehlk...@gmail.com> ha scritto:
>
> Consistency?
>
> // Same? Uh... no?
> auto __ = expr;
> auto [__] = expr;

In my proposal, I was not explicit whether the second line is required to call get<0>() or not. As it's currently worded, for consistency I have to assume get<0>() shall be called and the result bound to __. The binding can always be safely omitted, but the call can be omitted only if has no side effects. I understand why someone may believe this can be a defect of the proposal. However due to special nature of the name, it would not be unthinkable to explicitly allow the compiler to avoid the call.

> // Same? I hope so?
> auto [__] = expr;
> auto x = expr; auto __ = get<0>(x);
>
> // Same? Better be!
> auto [y] = expr;
> auto x = expr; auto y = get<0>(x);

These two are the same. Apart from its "throwaway" meaning, __ is still an identifier and works in the same way as any other identifier.

Alberto

Alberto Barbati

unread,
Mar 28, 2017, 5:15:09 PM3/28/17
to std-pr...@isocpp.org
Well... the starting point of the whole discussion is that my proposal would allow the use of __ in user code...

Alberto

Alberto Barbati

unread,
Mar 28, 2017, 5:28:30 PM3/28/17
to std-pr...@isocpp.org

> Il giorno 28 mar 2017, alle ore 15:55, Matthew Woehlke <mwoehlk...@gmail.com> ha scritto:
>
> The
> decomposition case I think would be best solved by allowing empty and
> nested declarations. See
> https://groups.google.com/a/isocpp.org/d/msg/std-proposals/gg3_eUhCuqo/HcippDFiBgAJ
> and following posts in the thread. This would let you write:
>
> auto [] = get_lock(); // no name
> auto [x, [], y] = get_tuple(); // middle element is unnamed
> auto [x, [a, b], y] = get_tuple(); // nested decomposition

This might actually be a good idea. I'd like to see a proposal in this direction.

Alberto

Viacheslav Usov

unread,
Mar 28, 2017, 5:46:16 PM3/28/17
to ISO C++ Standard - Future Proposals
On Tue, Mar 28, 2017 at 11:15 PM, Alberto Barbati <alberto...@gmail.com> wrote:

> Well... the starting point of the whole discussion is that my proposal would allow the use of __ in user code...

I responded to this: "As proposed by the OP: exactly as that declaration would do today".

Today, this is UB, per the standard.

Cheers,
V.

Thiago Macieira

unread,
Mar 28, 2017, 6:52:53 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 14:46:13 PDT Viacheslav Usov wrote:
> I responded to this: "As proposed by the OP: exactly as that declaration
> would do today".
>
> Today, this is UB, per the standard.

Ok, so amending: exactly as it is doing today in compilers that don't enforce
that __ is a reserved identifier.

Thiago Macieira

unread,
Mar 28, 2017, 6:54:46 PM3/28/17
to std-pr...@isocpp.org
On terça-feira, 28 de março de 2017 13:27:25 PDT Alberto Barbati wrote:
> > // Fetch the instance type of the receiver into result register.
> > __ movp(result, FieldOperand(string, HeapObject::kMapOffset));
> > __ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
>
> I don't see it much easier to read than:
>
> m_ movp(result, FieldOperand(string, HeapObject::kMapOffset));
> m_ movzxbl(result, FieldOperand(result, Map::kInstanceTypeOffset));
>
> especially when the macro m_ expands to some variation of "masm". Just my
> opinion.

It does to me, because the space is not as visible, so my first glance was
"m_movp", which is not at all what was meant.

Vicente J. Botet Escriba

unread,
Mar 29, 2017, 1:39:04 AM3/29/17
to std-pr...@isocpp.org
Le 28/03/2017 à 19:39, Nicol Bolas a écrit :
On Tuesday, March 28, 2017 at 1:29:57 PM UTC-4, Matthew Woehlke wrote:
On 2017-03-28 13:03, Thiago Macieira wrote:
> On terça-feira, 28 de março de 2017 09:53:51 PDT Zhihao Yuan wrote:
>>   auto [__, __] = get_tuple(...);
>>
>> should be physically equivalent to
>>
>>   get_tuple(...);
>>
>> thus, the result object is dropped on the floor.
>
> This should be equivalent to:
>
>         auto __ = get_tuple(...);

I would argue it should be equivalent to:

  auto __magic__ = get_tuple(...); // note: same as today
  auto __ = get<0>(__magic__);
  auto __ = get<1>(__magic__);

...so that in case of side effects, there is no observable behavior
difference. (The compiler is free to elide bits of the above if there
are provably no side effects.)

This almost makes me think we need "unnamed" and "ignored" to be
implemented separately :'(...

The question is this: will people actually want side effects of ignored parameters? Or more to the point, why exactly would you want those side effects?

I can't think of a case of a type that is decomposable where the decomposition `get` function has side effects. Well, with one exception: variant types. And the side effect there is that you get a thrown exception.

variant is not supoorted by structure binding :(

Vicente

Nicol Bolas

unread,
Mar 29, 2017, 9:38:32 AM3/29/17
to ISO C++ Standard - Future Proposals

More accurately, `variant` does not provide the things structured binding requires. My point is that, with `__` meaning to not invoke `get` at all, you could support `variant` and similar types.

TONGARI J

unread,
Mar 29, 2017, 11:23:27 AM3/29/17
to ISO C++ Standard - Future Proposals
On Tuesday, March 28, 2017 at 9:55:54 PM UTC+8, Matthew Woehlke wrote:
The decomposition case I think would be best solved by allowing empty and
nested declarations. See
https://groups.google.com/a/isocpp.org/d/msg/std-proposals/gg3_eUhCuqo/HcippDFiBgAJ
and following posts in the thread. This would let you write:

  auto [] = get_lock(); // no name
  auto [x, [], y] = get_tuple(); // middle element is unnamed
  auto [x, [a, b], y] = get_tuple(); // nested decomposition

Both solve the simple case, but both also have additional but
non-overlapping usefulness. I'm inclined to think that both are useful.

While I like the idea, but compilers probably don't. In the following example:
auto [[a, b], c] = get_tuple();

"[["conflicts with the attribute syntax.

TONGARI J

unread,
Mar 29, 2017, 11:43:10 AM3/29/17
to ISO C++ Standard - Future Proposals
On Wednesday, March 29, 2017 at 12:34:29 AM UTC+8, Brittany Friedman wrote:
Instead of __, I'd propose using ?. For example auto ? = scope_guard{...}. ? isn't allowed in identifiers so it shouldn't conflict with existing nonconformant code. ? is also shorter :)

You get my support :)
FWIW, I have developed a "template declname parameter" feature which also uses `?` to represent "unnamed".
That said, for lifetime extension, I'd prefer p0577.

Vicente J. Botet Escriba

unread,
Mar 29, 2017, 12:32:58 PM3/29/17
to std-pr...@isocpp.org
Your point was not clear enough ;-)
Are you serious about providing  structured binding support for variant types?

Vicente

Vitali Lovich

unread,
Mar 29, 2017, 11:41:49 PM3/29/17
to std-pr...@isocpp.org
On Tue, Mar 28, 2017 at 10:52 AM Thiago Macieira <thi...@macieira.org> wrote:
On terça-feira, 28 de março de 2017 09:53:51 PDT Zhihao Yuan wrote:
> Whether a call to get<0>(anon) being made
> certainly has difference, because it can have
> observable effect.

It does not, so it cannot have an observable effect.
doesnt it? If a function returns a Shared_ptr of a string and string_view that references the string, if you do:

    auto __ = getstr()
    auto [__, view] = getstr()

The behavior is observably different between the two cases depending on whether the compiler elides the get(0).  If you elide the get(0) in the second example isn't view going to point potentially freed memory?  It seems like there needs to be a distinction for structured binding between "don't care about name but keep alive for RAII" vs "don't care about value at all".  There may be cases in the former where a compiler finds room for optimization so it'll be equivalent in many cases.  It also has the added benefit of ensuring that the performance and lifetime behavior is identical to when you provide an identifier which is great for consistency and teachability.

Personally I think the "ignore" semantic is not as interesting - if performance is a concern then you'll have to be slightly more explicit or if it's common enough a separate mechanism can be developed.


--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/2235919.4GAIbDEcRC%40tjmaciei-mobl1.

Thiago Macieira

unread,
Mar 30, 2017, 12:12:48 AM3/30/17
to std-pr...@isocpp.org
On quarta-feira, 29 de março de 2017 20:41:37 PDT Vitali Lovich wrote:
> > It does not, so it cannot have an observable effect.
>
> doesnt it? If a function returns a Shared_ptr of a string and string_view
> that references the string, if you do:

Can you be more specific what this function returns? "A shared_ptr of a string
and a string_view" does not make sense, since shared_ptr only takes one
template parameter.

I'll analyse the rest when you post your reply.
Message has been deleted

Raffaele Rossi

unread,
Mar 30, 2017, 4:12:46 AM3/30/17
to ISO C++ Standard - Future Proposals
Wouldn't it be much better to have a concept of Context? I am taking inspiration from python (I know they use it for RAII, but that is a different discussion).

The code might look like:

  void foo() {
    // do stuff
    with (unique_lock{mutex}) {
      // critical code
    }
    // other stuff
  }

Then, for prettiness and to avoid unnecessary indentations, when the Context extends till the end of the parent scope, it can just be a declaration:

  void foo() {
    with unique_lock{mutex};
    // critical code
  }

You can also nest Contexts:

  void foo() {
    with unique_lock{mutex1};
    with unique_lock{mutex2};
    // etc
  }

Also, by having a proper concept of Context, compilers and static analysis tools would have more information available.

I don't know about the decomposition side of things, but perhaps using, say @  instead? But I have to admit I still haven't understood the difference with std::ignore (perhaps I have homework to do):

    auto [x, @, z] = expr;

Is anything of this any useful at all?

Matthew Woehlke

unread,
Mar 30, 2017, 10:29:04 AM3/30/17
to std-pr...@isocpp.org
On 2017-03-30 04:12, Raffaele Rossi wrote:
> Wouldn't it be much better to have a concept of Context? I am taking
> inspiration from python (I know they use it for RAII, but that is a
> different discussion).
>
> The code might look like:
>
> void foo() {
> // do stuff
> with (unique_lock{mutex}) {
> // critical code
> }
> // other stuff
> }

Or, without needing to introduce a new keyword:

void foo() {
// do stuff
using (unique_lock{mutex}) {
// critical code
}
// other stuff
}

We could support both:

using (expression) { ... }
using (declaration = expression) { ... }

...though of course the latter is equivalent to:

if (declaration = expression; true)

...or, y'know, just using some bare {}'s, which is probably why no one
has been enthusiastic about such a proposal. That may also be why this
direction has not been pursued more enthusiastically; anonymous
variables and/or lifetime extension just seem like a better solution...

(I'm confident this has come up before...)

--
Matthew

Nicol Bolas

unread,
Mar 30, 2017, 10:36:10 AM3/30/17
to ISO C++ Standard - Future Proposals
On Thursday, March 30, 2017 at 4:12:46 AM UTC-4, Raffaele Rossi wrote:
Wouldn't it be much better to have a concept of Context?

Why would I want to introduce a whole new scope when simply declaring an unnamed variable is sufficient? It's adding pointless braces for something that C++ gives by default.

Other languages use this syntax because they don't provide RAII by default. C++ does, so there's no need for explicit syntax to say what we normally have.

Raffaele Rossi

unread,
Mar 30, 2017, 12:25:39 PM3/30/17
to ISO C++ Standard - Future Proposals
You only add a scope if you need it, i.e to lock only a section of a function, in which case you have to create a scope anyway:

void foo() {
    // do stuff
    {
        unique_lock __{mutex};
    }
}

And between the two, doing using(...) { } is also more explicit on the intention, instead of just opening a "anonymous" scope, isn't it?

Alberto Barbati

unread,
Mar 30, 2017, 1:09:48 PM3/30/17
to std-pr...@isocpp.org

Il giorno 30 mar 2017, alle ore 10:08, raffael...@mavensecurities.com ha scritto:

Wouldn't it be much better to have a concept of Context? I am taking inspiration from python (I know they use it for RAII, but that is a different discussion).

The code might look like:

  void foo() {
    // do stuff
    with (unique_lock{mutex}) {
      // critical code
    }
    // other stuff
  }

Then, for prettiness and to avoid unnecessary indentations, when the Context extends till the end of the parent scope, it can just be a declaration:

  void foo() {
    with unique_lock{mutex};
    // critical code
  }

You can also nest Contexts:

  void foo() {
    with unique_lock{mutex1};
    with unique_lock{mutex2};
    // etc
  }

Also, by having a proper concept of Context, compilers and static analysis tools would have more information available.

This is essentially achieved by the proposal in P0577.

I don't know about the decomposition side of things, but perhaps using, say @  instead? But I have to admit I still haven't understood the difference with std::ignore (perhaps I have homework to do):

    auto [x, @, z] = expr;


In my humble opinion, the only sensible choices are an identifier with special meaning (like __), the empty brackets [] or nothing at all. All of them have pros and cons, but all other suggestions about inventing new punctuation (be it @, ? or whatever) are too much a waste of lexical space to be considered.

A.

Alberto Barbati

unread,
Mar 30, 2017, 1:31:45 PM3/30/17
to std-pr...@isocpp.org

> Il giorno 30 mar 2017, alle ore 05:41, Vitali Lovich <vlo...@gmail.com> ha scritto:
>
> If a function returns a Shared_ptr of a string and string_view that references the string, if you do:
>
> auto __ = getstr()
> auto [__, view] = getstr()
>
> The behavior is observably different between the two cases depending on whether the compiler elides the get(0). If you elide the get(0) in the second example isn't view going to point potentially freed memory?

Why would view point to potentially freed memory? Decomposition declaration works like this:

1) initialize a hidden "main" object using the initializer
2) bind "element" names to subobjects of the main objects

The elements are guaranteed not to outlive the main object. Point 2) can be obtained differently according to the type of the main object. In the most general case, get<>() may be invoked. The Standard does not mandate that get<>() function shall have no side effects, but, really, the intent should be to get hold of a reference of a subobject of the main object, no significant task should be performed.

> It seems like there needs to be a distinction for structured binding between "don't care about name but keep alive for RAII" vs "don't care about value at all".

In the case of a decomposition declaration, all RAII logic should performed by the main object itself, since it's guaranteed to be destroyed after the elements. Having an element perform RAII logic is a misuse of the feature. Remember that you are not required to always decompose the object with this syntax.

> Personally I think the "ignore" semantic is not as interesting - if performance is a concern then you'll have to be slightly more explicit or if it's common enough a separate mechanism can be developed.

I believe it is interesting. However, I understand what you mean. For regular declarations we definitely want the "keep" semantic, I guess we agree on that. For decomposition declarations we might get either a "keep" or "ignore" semantic. In most cases (e.g.: aggregates, arrays and objects whose get() functions have no side effect) the result is the same. In the remaining corner case, I expect the "ignore" semantic to be more useful, but this is a personal opinion. It's a fact, however that if we mandate the "ignore" semantic, the programmer might easily get the "keep" by just providing any identifier different from __. However if we mandate the "keep" semantic, there's no way to get the other one.

A.

Vitali Lovich

unread,
Mar 30, 2017, 5:40:46 PM3/30/17
to std-pr...@isocpp.org
tuple<shared_ptr<string>, string_view> getstr()

The 2nd argument is a view into the string owned by shared_ptr.

The semantics of whether or not the string view points to owned memory depends on the lifetime of the shared_ptr and my understanding of what you were saying is that the lifetime changes depending on whether the get() is done or ignored.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Vitali Lovich

unread,
Mar 30, 2017, 5:42:08 PM3/30/17
to std-pr...@isocpp.org
Ah. But I forgot now that with structured binding there's a hidden local variable anyway for the tuple itself.  I was thinking the compiler was smart and applied RVO to the individual elements directly.

Alberto Barbati

unread,
Mar 31, 2017, 2:49:47 AM3/31/17
to std-pr...@isocpp.org

Il giorno 30 mar 2017, alle ore 23:41, Vitali Lovich <vlo...@gmail.com> ha scritto:

Ah. But I forgot now that with structured binding there's a hidden local variable anyway for the tuple itself.  I was thinking the compiler was smart and applied RVO to the individual elements directly.

Exactly. All RAII logic is (or at least should be) performed by the "main" hidden object that is being decomposed. No get() function should ever depend on the side effects of other get() function on the same object, because otherwise the following valid code would become problematic:

auto x = getstr();
auto v = get<1>(x);

A. 

Richard Smith

unread,
Apr 2, 2017, 12:19:41 AM4/2/17
to std-pr...@isocpp.org
I don't think you need a reserved identifier for this, nor to change the meaning of any existing code (whether or not it uses a reserved identifier). It seems to me that your use cases could be addressed by allowing the identifier _ to declare multiple entities within a block scope. (If it is multiply declared, any reference to it would be ill-formed due to ambiguity; if it's only declared once, it can still be referenced for backwards compatibility, but such usage could be deprecated.)

Have you considered that possibility? It would give a better name (_ rather than __) and avoid "breaking" existing code that uses __.

On 27 Mar 2017 10:27 am, "Alberto Barbati" <alberto...@gmail.com> wrote:
Hello,

this is a draft for a proposal to add a special meaning to the identifier __ (double underscore) so that it can be used (even repeatedly in the same lexical scope) for all variables whose name is not important and that is no longer needed after declaration. The draft includes a few examples.

Is there any interest in this?

Thanks in advance,

Alberto

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.

To post to this group, send email to std-pr...@isocpp.org.

Magnus Fromreide

unread,
Apr 2, 2017, 3:33:55 AM4/2/17
to std-pr...@isocpp.org
On Sat, Apr 01, 2017 at 09:19:37PM -0700, Richard Smith wrote:
> I don't think you need a reserved identifier for this, nor to change the
> meaning of any existing code (whether or not it uses a reserved
> identifier). It seems to me that your use cases could be addressed by
> allowing the identifier _ to declare multiple entities within a block
> scope. (If it is multiply declared, any reference to it would be ill-formed
> due to ambiguity; if it's only declared once, it can still be referenced
> for backwards compatibility, but such usage could be deprecated.)
>
> Have you considered that possibility? It would give a better name (_ rather
> than __) and avoid "breaking" existing code that uses __.

If there are concerns about the use of __ due to it beeing used in real code
then that is way worse for _.

One common use of _ is as a macro name in gettextized GNU programs. Now, this
use doesn't clash with the proposed use case but I doubt they are the only
ones that have used the name.

Additionally the name _ is reserved for the library so it is not even ours
in the first place.

/MF

Thiago Macieira

unread,
Apr 2, 2017, 2:03:09 PM4/2/17
to std-pr...@isocpp.org
On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
> Have you considered that possibility? It would give a better name (_ rather
> than __) and avoid "breaking" existing code that uses __.

_ is not reserved to the compiler and is VERY often #defined to gettext.

Let's use __. At least we can point to V8 developers and tell them it's their
own fault.

Richard Smith

unread,
Apr 2, 2017, 3:28:54 PM4/2/17
to std-pr...@isocpp.org
On 2 April 2017 at 11:03, Thiago Macieira <thi...@macieira.org> wrote:
On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
> Have you considered that possibility? It would give a better name (_ rather
> than __) and avoid "breaking" existing code that uses __.

_ is not reserved to the compiler and is VERY often #defined to gettext.

Only as a function-like macro.

Let's use __.

Let's use the thing that works best for C++, sure. I am not (yet) convinced that's __.
 
At least we can point to V8 developers and tell them it's their
own fault.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
   Software Architect - Intel Open Source Technology Center

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Nicol Bolas

unread,
Apr 2, 2017, 3:45:38 PM4/2/17
to ISO C++ Standard - Future Proposals
On Sunday, April 2, 2017 at 3:28:54 PM UTC-4, Richard Smith wrote:
On 2 April 2017 at 11:03, Thiago Macieira <thi...@macieira.org> wrote:
On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
> Have you considered that possibility? It would give a better name (_ rather
> than __) and avoid "breaking" existing code that uses __.

_ is not reserved to the compiler and is VERY often #defined to gettext.

Only as a function-like macro.

Let's use __.

Let's use the thing that works best for C++, sure. I am not (yet) convinced that's __.

Well, let's look at the options.

You can't use nothing; that would create parsing ambiguities. So you have to put something there: either an identifier or something that is not an identifier.

If it is not an identifier, then it must be a keyword (new or old) or some form of punctuation. Adding a new keyword for something like this is rather silly. And I don't know of an old keyword that would make for a good placeholder.

You could use `[]` as I once suggested, piggybacking off of structured binding rules. But most other punctuation would be confusing or otherwise unexpected in a variable declaration.

If it is an identifier, then it must be a reserved identifier, to minimize code breakage when we change its meaning. The shortest reserved identifier is `_`, which is currently reserved for use by the implementation, but only for names in the global namespace. Which means that right now, this is 100% legal:

namespace foo
{
 
constexpr int _ = 20;
}

So changing the meaning of that code is a non-starter.

The second shortest reserved identifiers are of the form `_*`, where `*` is an uppercase letter or `_`. These are reserved by the implementation for any use. And implementations are more easily changed than user code.

So from my perspective, `__` is the most viable identifier.

Alberto Barbati

unread,
Apr 2, 2017, 3:56:08 PM4/2/17
to std-pr...@isocpp.org
Il giorno 02 apr 2017, alle ore 20:03, Thiago Macieira <thi...@macieira.org> ha scritto:

>> On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
>> Have you considered that possibility? It would give a better name (_ rather
>> than __) and avoid "breaking" existing code that uses __.
>
> _ is not reserved to the compiler and is VERY often #defined to gettext.

Thank you Richard for your suggestion which is very interesting, since it provides good insights about a possible wording. As for the name, I believe Thiago and Magnus raised valid concerns, though. It's true that the we might choose _ without breaking existing code. However defining _ as a macro is currently valid and apparently widely used. I believe we therefore have only two choices: either we make such uses undefined behavior (upsetting a lot of people) or we choose wording to avoid that (making the feature essentially unusable for users of all libraries like gettext). None of the two approaches seems very good. Is there a third option?

__ seems somewhat safer and less controversial.

Alberto

Richard Smith

unread,
Apr 2, 2017, 4:10:38 PM4/2/17
to std-pr...@isocpp.org
As noted, gettext defines _ as a function-like macro, so there seems to be no technical problem for users of gettext (although some might consider overloading the meaning of _ in this way to be a readability problem).

__ seems somewhat safer and less controversial.

I would expect you'll find controversy if you pick a worse name in order to avoid collision with a macro name that some would already consider to be poorly chosen, so I don't think it's clear which will be less controversial.

Richard Smith

unread,
Apr 2, 2017, 4:13:36 PM4/2/17
to std-pr...@isocpp.org
On 2 April 2017 at 12:45, Nicol Bolas <jmck...@gmail.com> wrote:
On Sunday, April 2, 2017 at 3:28:54 PM UTC-4, Richard Smith wrote:
On 2 April 2017 at 11:03, Thiago Macieira <thi...@macieira.org> wrote:
On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
> Have you considered that possibility? It would give a better name (_ rather
> than __) and avoid "breaking" existing code that uses __.

_ is not reserved to the compiler and is VERY often #defined to gettext.

Only as a function-like macro.

Let's use __.

Let's use the thing that works best for C++, sure. I am not (yet) convinced that's __.

Well, let's look at the options.

You can't use nothing; that would create parsing ambiguities. So you have to put something there: either an identifier or something that is not an identifier.

If it is not an identifier, then it must be a keyword (new or old) or some form of punctuation. Adding a new keyword for something like this is rather silly. And I don't know of an old keyword that would make for a good placeholder.

You could use `[]` as I once suggested, piggybacking off of structured binding rules. But most other punctuation would be confusing or otherwise unexpected in a variable declaration.

If it is an identifier, then it must be a reserved identifier, to minimize code breakage when we change its meaning.

As I pointed out, this is an incorrect conclusion. There is no necessity for any code breakage here, and there is no need to pick a reserved identifier: the core functionality of this proposal does not require that the identifier be unusable within its scope, and if we don't add that restriction, this is strictly an extension.

The shortest reserved identifier is `_`, which is currently reserved for use by the implementation, but only for names in the global namespace. Which means that right now, this is 100% legal:

namespace foo
{
 
constexpr int _ = 20;
}

So changing the meaning of that code is a non-starter.

The second shortest reserved identifiers are of the form `_*`, where `*` is an uppercase letter or `_`. These are reserved by the implementation for any use. And implementations are more easily changed than user code.

So from my perspective, `__` is the most viable identifier.

--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.

Alberto Barbati

unread,
Apr 2, 2017, 5:11:18 PM4/2/17
to std-pr...@isocpp.org
Il giorno 02 apr 2017, alle ore 22:10, Richard Smith <ric...@metafoo.co.uk> ha scritto:

On 2 April 2017 at 12:56, Alberto Barbati <alberto...@gmail.com> wrote:
Il giorno 02 apr 2017, alle ore 20:03, Thiago Macieira <thi...@macieira.org> ha scritto:

>> On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
>> Have you considered that possibility? It would give a better name (_ rather
>> than __) and avoid "breaking" existing code that uses __.
>
> _ is not reserved to the compiler and is VERY often #defined to gettext.

Thank you Richard for your suggestion which is very interesting, since it provides good insights about a possible wording. As for the name, I believe Thiago and Magnus raised valid concerns, though. It's true that the we might choose _ without breaking existing code. However defining _ as a macro is currently valid and apparently widely used. I believe we therefore have only two choices: either we make such uses undefined behavior (upsetting a lot of people) or we choose wording to avoid that (making the feature essentially unusable for users of all libraries like gettext). None of the two approaches seems very good. Is there a third option?

As noted, gettext defines _ as a function-like macro, so there seems to be no technical problem for users of gettext (although some might consider overloading the meaning of _ in this way to be a readability problem).

I guess the proposal might use an assessment of the usage of _ as a macro name.

However, I am a bit worried about this:

  unique_lock _ (mutex1); // ok, _ is an identifier
  unique_lock _(mutex2); // ops! may not compile if I #include gettext


__ seems somewhat safer and less controversial.

I would expect you'll find controversy if you pick a worse name in order to avoid collision with a macro name that some would already consider to be poorly chosen, so I don't think it's clear which will be less controversial.

Duly noted. By the way, I personally don’t think __ is much worse than _. This seems very subjective to me.

Alberto

Nicol Bolas

unread,
Apr 2, 2017, 6:45:50 PM4/2/17
to ISO C++ Standard - Future Proposals
On Sunday, April 2, 2017 at 4:13:36 PM UTC-4, Richard Smith wrote:
On 2 April 2017 at 12:45, Nicol Bolas <jmck...@gmail.com> wrote:
On Sunday, April 2, 2017 at 3:28:54 PM UTC-4, Richard Smith wrote:
On 2 April 2017 at 11:03, Thiago Macieira <thi...@macieira.org> wrote:
On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
> Have you considered that possibility? It would give a better name (_ rather
> than __) and avoid "breaking" existing code that uses __.

_ is not reserved to the compiler and is VERY often #defined to gettext.

Only as a function-like macro.

Let's use __.

Let's use the thing that works best for C++, sure. I am not (yet) convinced that's __.

Well, let's look at the options.

You can't use nothing; that would create parsing ambiguities. So you have to put something there: either an identifier or something that is not an identifier.

If it is not an identifier, then it must be a keyword (new or old) or some form of punctuation. Adding a new keyword for something like this is rather silly. And I don't know of an old keyword that would make for a good placeholder.

You could use `[]` as I once suggested, piggybacking off of structured binding rules. But most other punctuation would be confusing or otherwise unexpected in a variable declaration.

If it is an identifier, then it must be a reserved identifier, to minimize code breakage when we change its meaning.

As I pointed out, this is an incorrect conclusion. There is no necessity for any code breakage here, and there is no need to pick a reserved identifier: the core functionality of this proposal does not require that the identifier be unusable within its scope, and if we don't add that restriction, this is strictly an extension.

But that makes it a different proposal. This proposal is about having a scope-bound object which cannot be later referenced, which has a name that is generated by the compiler. That's what the proposal is for: "for all variables whose name is not important and that is no longer needed after declaration".

You are talking about something else.

Nicol Bolas

unread,
Apr 2, 2017, 6:50:51 PM4/2/17
to ISO C++ Standard - Future Proposals


On Sunday, April 2, 2017 at 4:10:38 PM UTC-4, Richard Smith wrote:
On 2 April 2017 at 12:56, Alberto Barbati <alberto...@gmail.com> wrote:
Il giorno 02 apr 2017, alle ore 20:03, Thiago Macieira <thi...@macieira.org> ha scritto:

>> On sábado, 1 de abril de 2017 21:19:37 PDT Richard Smith wrote:
>> Have you considered that possibility? It would give a better name (_ rather
>> than __) and avoid "breaking" existing code that uses __.
>
> _ is not reserved to the compiler and is VERY often #defined to gettext.

Thank you Richard for your suggestion which is very interesting, since it provides good insights about a possible wording. As for the name, I believe Thiago and Magnus raised valid concerns, though. It's true that the we might choose _ without breaking existing code. However defining _ as a macro is currently valid and apparently widely used. I believe we therefore have only two choices: either we make such uses undefined behavior (upsetting a lot of people) or we choose wording to avoid that (making the feature essentially unusable for users of all libraries like gettext). None of the two approaches seems very good. Is there a third option?

As noted, gettext defines _ as a function-like macro, so there seems to be no technical problem for users of gettext (although some might consider overloading the meaning of _ in this way to be a readability problem).

But we can't do that. As previously mentioned, this does break valid code:

namespace Name
{
 
int _ = 5;
};

`_` is only reserved for implementation use in the global namespace. That name is not in a global namespace, so it's perfectly fine for users to use it.

Using it for this feature would change this code, such that the variable is no longer accessible.

__ seems somewhat safer and less controversial.

I would expect you'll find controversy if you pick a worse name in order to avoid collision with a macro name that some would already consider to be poorly chosen, so I don't think it's clear which will be less controversial.

I've yet to see evidence that `__` is in any technical way worse than `_`.

Thiago Macieira

unread,
Apr 2, 2017, 11:48:26 PM4/2/17
to std-pr...@isocpp.org
On domingo, 2 de abril de 2017 13:10:14 PDT Richard Smith wrote:
> As noted, gettext defines _ as a function-like macro,

Even as a function-like macro, it wouldn't work:

std::lock_guard _(mutex);

Barry Revzin

unread,
Apr 3, 2017, 3:37:28 PM4/3/17
to ISO C++ Standard - Future Proposals

If it is an identifier, then it must be a reserved identifier, to minimize code breakage when we change its meaning.

As I pointed out, this is an incorrect conclusion. There is no necessity for any code breakage here, and there is no need to pick a reserved identifier: the core functionality of this proposal does not require that the identifier be unusable within its scope, and if we don't add that restriction, this is strictly an extension.


I think the logical extreme of this idea is to not pick any identifier at all - simply allow hiding declarations in the same scope. So from the original paper's examples, using __ to declare multiple variables in the same scope just works not because of some special magic bestowed upon the identifier "__", but instead because you're actually declaring multiple variables in the same scope named "__". You'd have no way of accessing the earlier versions of __, but then you don't want to anyway. I don't know how to get the compiler to not warn against not using the last incarnation of __ though. That just may be a "teach the compiler that this is a convention that people want to use" kind of thing. 

We'd have to change the scope rules for names, but I'm not sure that's any worse than bestowing magic language meaning on a specific identifier. 

Matthew Woehlke

unread,
Apr 3, 2017, 3:55:16 PM4/3/17
to std-pr...@isocpp.org
On 2017-04-03 15:37, Barry Revzin wrote:
> I think the logical extreme of this idea is to not pick any identifier at
> all - simply allow hiding declarations in the same scope. So from the
> original paper's examples, using __ to declare multiple variables in the
> same scope just works not because of some special magic bestowed upon the
> identifier "__", but instead because you're actually declaring multiple
> variables in the same scope named "__". You'd have no way of accessing the
> earlier versions of __, but then you don't want to anyway. I don't know how
> to get the compiler to not warn against not using the last incarnation of
> __ though. That just may be a "teach the compiler that this is a convention
> that people want to use" kind of thing.

That seems like a recipe for bugs. We have enough problems with -Wshadow
as it is, let alone making the situation *worse*...

--
Matthew

T. C.

unread,
Apr 3, 2017, 4:28:57 PM4/3/17
to ISO C++ Standard - Future Proposals
I think the original idea Richard posited is that there is no hiding. Instead, if you declare multiple variables with the same name in the same scope, you can't access *any* of them. Name lookup will simply find all the declarations and declare an ambiguity at that point.

Alberto Barbati

unread,
Apr 4, 2017, 3:55:02 AM4/4/17
to std-pr...@isocpp.org

Il giorno 03 apr 2017, alle ore 22:28, T. C. <rs2...@gmail.com> ha scritto:

On Monday, April 3, 2017 at 3:55:16 PM UTC-4, Matthew Woehlke wrote:

Richard proposal is very interesting indeed, however as someone has already pointed out it's a completely different proposal. His proposal avoids special treatment of the "placeholder" identifier, which may be good, but my whole point is that I do want to have a special treatment. Having the maybe_unused automatically applied without an explicit attribute is an essential part of the proposal, as well as the requirement to omit the call to the get() function if the placeholder  is used in decomposition declarations. Having a special identifier seems to me the most concise way to achieve that.

Alberto

Bengt Gustafsson

unread,
Apr 4, 2017, 4:46:37 PM4/4/17
to ISO C++ Standard - Future Proposals
I would like Richards idea of allowing redeclaration of _ and disallowing access to any of those multiple instances if it wasn't for the unfortunate _("Text to translate") use that is really widespread. On the other hand a macro definition with parameters (such as _) does not get expanded if no parameters are provided, so at least for some cases this could still work.

I have previously suggested using the ? token for this same purpose. As ? is currently used only for an infix operator I don't think this would cause any ambiguities, but I'm not entirely convinced... can anyone find a case where a ternary ? and a declarator named ? would clash?


Thiago Macieira

unread,
Apr 5, 2017, 12:52:04 AM4/5/17
to std-pr...@isocpp.org
Em terça-feira, 4 de abril de 2017, às 13:46:36 PDT, Bengt Gustafsson
escreveu:
> On the other hand a
> macro definition with parameters (such as _) does not get expanded if no
> parameters are provided, so at least for some cases this could still work.

Yet there's one very important use that wouldn't be included: variable
declaration.

Alberto Barbati

unread,
Apr 5, 2017, 2:16:54 AM4/5/17
to std-pr...@isocpp.org


> Il giorno 04 apr 2017, alle ore 22:46, Bengt Gustafsson <bengt.gu...@beamways.com> ha scritto:
>
> I have previously suggested using the ? token for this same purpose. As ? is currently used only for an infix operator I don't think this would cause any ambiguities, but I'm not entirely convinced... can anyone find a case where a ternary ? and a declarator named ? would clash?

Using a punctuation would require significant changes in the grammar, since we would have to allow it in places where only identifiers are allowed today. Non mentioning that we might lose the possibility to use the symbol for other uses. For what is perceived as a little feature, the cost seems too high. Just my opinion.

Alberto

Derek Ross

unread,
Apr 5, 2017, 11:06:15 AM4/5/17
to ISO C++ Standard - Future Proposals
Maybe an existing keyword could be used instead. Something like:
    unique_lock auto {lock};
or
    unique_lock default {lock};

or some other keyword.

hun.nem...@gmail.com

unread,
Apr 5, 2017, 11:22:12 AM4/5/17
to ISO C++ Standard - Future Proposals
Was a #unique-id,  #id  or #__ preprocessor like syntax considered before for this reason?

void demo_scope_exit_fail_success()
{
 std::ostringstream out {};
 auto lam = [&]{out << "called ";};
 try{
   scope_exit     #id {[&]{out << "always ";}};
   scope_success  #unique_id {[&]{out << "not ";}};
   scope_fail     #__ {lam};
   ...


Peter

Alberto Barbati

unread,
Apr 10, 2017, 12:01:28 AM4/10/17
to std-pr...@isocpp.org

Il giorno 03 apr 2017, alle ore 00:45, Nicol Bolas <jmck...@gmail.com> ha scritto:

This proposal is about having a scope-bound object which cannot be later referenced, which has a name that is generated by the compiler. That's what the proposal is for: "for all variables whose name is not important and that is no longer needed after declaration".

Sorry to have left the thread for so long. After some pondering, although the __ approach is still on the table, I have decided to explore a bit further other options that do not require reserving an identifier, in particular the one suggested by Nicol Bolas. The fact is that I realized C++17 already has a tool that creates an object that cannot be referenced...  that tool is decomposition declaration itself. With just three tweaks, which would make for a pure extension, we can achieve both goals of my proposal.

Tweak #1

Allow identifiers in a decomposition declaration to be omitted. So in

    auto [x, , z] = func();

the second element is not named so the corresponding element needs not be bound and get<1>() is guaranteed not to be called (however, we might still check that it might have been called, for consistency).

This tweak alone solves goal #2 of the proposal and is probably more elegant: since there's no name, there's little room for misunderstanding about the semantic.

Tweak #2

Make [] a special case by allowing it for all types: in this particular case, tuple_size<>, tuple_element<> and  get<>() functions are not required nor called. We would therefore be able to write:

    auto [] = lock_guard{m};

even if lock_guard does not have a tuple-like interface. This actually solves goal #1! In fact, the declaration instantiate the "hidden" object, which is destroyed at the end of scope, as usual. It  simply doesn't bind it to a name.

There's only one drawback: since decomposition declarations mandate the use of auto, the syntax seems unnecessarily verbose.

Tweak #3

Allow the decl-specifier-seq in a decomposition declaration to be different from auto. This would allow to write the code above more concisely:

    lock_guard [] {m};

Incidentally, this tweak would provide greater control over "normal" decomposition declarations too, giving a concise syntax to coerce the type of the hidden object.

Tweak #3 is probably the most problematic part. I admit I didn't follow the discussion that brought to the current wording of decomposition declarations, but I'm sure it has been discussed before and if there weren't problems it would probably have been allowed already. If anyone has pointers to share about that they are definitely welcome.

Alberto


Domen Vrankar

unread,
Apr 10, 2017, 2:53:00 AM4/10/17
to std-pr...@isocpp.org
2017-04-10 1:10 GMT+02:00 Alberto Barbati <alberto...@gmail.com>:

Il giorno 03 apr 2017, alle ore 00:45, Nicol Bolas <jmck...@gmail.com> ha scritto:

This proposal is about having a scope-bound object which cannot be later referenced, which has a name that is generated by the compiler. That's what the proposal is for: "for all variables whose name is not important and that is no longer needed after declaration".

Sorry to have left the thread for so long. After some pondering, although the __ approach is still on the table, I have decided to explore a bit further other options that do not require reserving an identifier, in particular the one suggested by Nicol Bolas. The fact is that I realized C++17 already has a tool that creates an object that cannot be referenced...  that tool is decomposition declaration itself. With just three tweaks, which would make for a pure extension, we can achieve both goals of my proposal.

Tweak #1

Allow identifiers in a decomposition declaration to be omitted. So in

    auto [x, , z] = func();

the second element is not named so the corresponding element needs not be bound and get<1>() is guaranteed not to be called (however, we might still check that it might have been called, for consistency).

This tweak alone solves goal #2 of the proposal and is probably more elegant: since there's no name, there's little room for misunderstanding about the semantic.

Won't this be annoying to read? It might be just me but I would still prefer a placeholder for something like that.

Regards,

Domen

Matthew Woehlke

unread,
Apr 10, 2017, 9:53:37 AM4/10/17
to std-pr...@isocpp.org
On 2017-04-03 16:28, T. C. wrote:
> if you declare multiple variables with the same name in the same
> scope, you can't access *any* of them. Name lookup will simply find
> all the declarations and declare an ambiguity at that point.

How's that going to work?

auto x = ...;
... lots of code ...
foo(..., x, ...);
... lots more code ...
auto x = ...;

The compiler isn't going to parse the entire scope for variable
declarations first in order to "retroactively" forbid the earlier use of
`x`.

Is the intent that `x` can be used until the second declaration? That's
just... bizarre.

--
Matthew
Reply all
Reply to author
Forward
0 new messages