throwaway variable

434 views
Skip to first unread message

Dmitry Banshchikov

unread,
Feb 19, 2016, 3:05:04 PM2/19/16
to ISO C++ Standard - Future Proposals
Hi!

Does anyone see helpfulness of such solution:

for(auto _ : {1, 2, 3})
{
}

Variable with name "_" has an implicit unused attribute set.


-- 

Dmitry Banschikov

Ville Voutilainen

unread,
Feb 19, 2016, 3:06:01 PM2/19/16
to ISO C++ Standard - Future Proposals
On 19 February 2016 at 22:05, Dmitry Banshchikov <m...@ubique.spb.ru> wrote:
> Hi!
>
> Does anyone see helpfulness of such solution:
>
> for(auto _ : {1, 2, 3})
> {
> }
>
> Variable with name "_" has an implicit unused attribute set.


Certainly, it has been discussed before, but hasn't progressed in a while:
http://cplusplus.github.io/EWG/ewg-active.html#35

Patrice Roy

unread,
Feb 19, 2016, 3:06:34 PM2/19/16
to std-pr...@isocpp.org
I often use _ as «uninteresting but needed» variables such as lock_guards. Please don't break my code :)

--

---
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.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-proposals/.

Matthew Woehlke

unread,
Feb 19, 2016, 3:16:28 PM2/19/16
to std-pr...@isocpp.org
On 2016-02-19 15:06, Patrice Roy wrote:
> I often use _ as «uninteresting but needed» variables such as lock_guards.
> Please don't break my code :)

I don't think this would break your code (except that using '_' is
probably a no-go due to its use for GNU translations). The idea is that
the variable exists, but cannot be named, and isn't used except for side
effects. A lock_guard is certainly a side effect. (Critically, the
lifetime of such a variable is not different from a regular variable.)

Hmm... I wonder if `.` could be used...

--
Matthew

Ville Voutilainen

unread,
Feb 19, 2016, 3:20:27 PM2/19/16
to ISO C++ Standard - Future Proposals
If anyone wants to work on a proposal/implementation for it, I recommend talking
to Jeffrey Yasskin.

Sean Middleditch

unread,
Feb 20, 2016, 3:46:24 PM2/20/16
to ISO C++ Standard - Future Proposals, mwoehlk...@gmail.com
On Friday, February 19, 2016 at 12:16:28 PM UTC-8, Matthew Woehlke wrote:
On 2016-02-19 15:06, Patrice Roy wrote:
> I often use _ as «uninteresting but needed» variables such as lock_guards.
> Please don't break my code :)

I don't think this would break your code (except that using '_' is
probably a no-go due to its use for GNU translations). The idea is that
the variable exists, but cannot be named, and isn't used except for side

While that may be for Roy's example, I think the potential for breakage remains. _ today is a legal identifier with no special semantics. You propose to change that. I think we'd need a new identifier that is not currently legal (or far less likely to be in use).
 
effects. A lock_guard is certainly a side effect. (Critically, the
lifetime of such a variable is not different from a regular variable.)

Hmm... I wonder if `.` could be used...

Actually, __ (double underscore) might work, since all identifiers with leading double underscores are technically reserved (although iirc they're reserved for the implementation, not the standard).
 

--
Matthew

Jeffrey Yasskin

unread,
Feb 20, 2016, 5:11:51 PM2/20/16
to std-pr...@isocpp.org
I'm not actively working on this, and nobody will be stepping on my
toes by taking it over. I do still think that __ is the most likely
name for the concept.

Ville Voutilainen

unread,
Feb 20, 2016, 5:15:43 PM2/20/16
to ISO C++ Standard - Future Proposals
On 21 February 2016 at 00:11, 'Jeffrey Yasskin' via ISO C++ Standard -
Future Proposals <std-pr...@isocpp.org> wrote:
>> If anyone wants to work on a proposal/implementation for it, I recommend talking
>> to Jeffrey Yasskin.
> I'm not actively working on this, and nobody will be stepping on my
> toes by taking it over. I do still think that __ is the most likely
> name for the concept.


My recommendation isn't about stepping on anyone's toes, but rather
getting familiar with the existing design issues of the idea. ;)

Zhihao Yuan

unread,
Feb 20, 2016, 5:22:02 PM2/20/16
to std-pr...@isocpp.org
On Sat, Feb 20, 2016 at 4:11 PM, 'Jeffrey Yasskin' via ISO C++
Standard - Future Proposals <std-pr...@isocpp.org> wrote:
> I do still think that __ is the most likely
> name for the concept.

I'd rather see a syntax like `if` but not branching:

with (locking()) {
// ...
}

with (auto f = open_file(...))
// ...

For this use case,

for(auto _ : {1, 2, 3})
{
}

I think, maybe, we can just allow range-for to have no declarator:

for ({1, 2, 3})
{
}

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://bit.ly/blog4bsd

Jeffrey Yasskin

unread,
Feb 20, 2016, 7:13:42 PM2/20/16
to std-pr...@isocpp.org
On Sat, Feb 20, 2016 at 2:21 PM, Zhihao Yuan <z...@miator.net> wrote:
> On Sat, Feb 20, 2016 at 4:11 PM, 'Jeffrey Yasskin' via ISO C++
> Standard - Future Proposals <std-pr...@isocpp.org> wrote:
>> I do still think that __ is the most likely
>> name for the concept.
>
> I'd rather see a syntax like `if` but not branching:

Did you read http://cplusplus.github.io/EWG/ewg-active.html#35?

Zhihao Yuan

unread,
Feb 20, 2016, 8:13:04 PM2/20/16
to std-pr...@isocpp.org
On Sat, Feb 20, 2016 at 6:13 PM, 'Jeffrey Yasskin' via ISO C++
Standard - Future Proposals <std-pr...@isocpp.org> wrote:
> On Sat, Feb 20, 2016 at 2:21 PM, Zhihao Yuan <z...@miator.net> wrote:
>> On Sat, Feb 20, 2016 at 4:11 PM, 'Jeffrey Yasskin' via ISO C++
>> Standard - Future Proposals <std-pr...@isocpp.org> wrote:
>>> I do still think that __ is the most likely
>>> name for the concept.
>>
>> I'd rather see a syntax like `if` but not branching:
>
> Did you read http://cplusplus.github.io/EWG/ewg-active.html#35?

I didn't.

__ is a simple (maybe) solution, may have more uses, but I hope,
in many cases, we can just let the C++ syntax itself not introducing
a name from the beginning, and I think that's nicer.

Thiago Macieira

unread,
Feb 21, 2016, 1:07:36 AM2/21/16
to std-pr...@isocpp.org
On sábado, 20 de fevereiro de 2016 12:46:24 PST Sean Middleditch wrote:
> Actually, __ (double underscore) might work, since all identifiers with
> leading double underscores are technically reserved (although iirc they're
> reserved for the implementation, not the standard).

And yet they're abused.

https://github.com/v8/v8/search?q=define+__&type=Code

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

Viacheslav Usov

unread,
Feb 21, 2016, 8:55:18 AM2/21/16
to std-pr...@isocpp.org
On Fri, Feb 19, 2016 at 9:06 PM, Patrice Roy <patr...@gmail.com> wrote:

> I often use _ as «uninteresting but needed» variables such as lock_guards. Please don't break my code :)

I would even say that this case, "uninteresting but needed" is more interesting. It would be nice to have a language construct that creates an "anonymous" variable in the current scope. Alternatively, this could be conceptualized as a temporary whose lifetime is extended till the end of the current scope.

Cheers,
V.

Arthur O'Dwyer

unread,
Feb 22, 2016, 1:30:49 AM2/22/16
to ISO C++ Standard - Future Proposals
On Saturday, February 20, 2016 at 2:22:02 PM UTC-8, Zhihao Yuan wrote:
On Sat, Feb 20, 2016 at 4:11 PM, 'Jeffrey Yasskin' via ISO C++
Standard - Future Proposals <std-pr...@isocpp.org> wrote:
> I do still think that __ is the most likely
> name for the concept.

I'd rather see a syntax like `if` but not branching:

  with (locking()) {
    // ...
  }

  with (auto f = open_file(...))
    // ...

For this use case,

  for(auto _ : {1, 2, 3})
  {
  }

I think, maybe, we can just allow range-for to have no declarator:

  for ({1, 2, 3})
  {
  }

I suspect that that would produce ambiguities in the grammar (allowing either a declaration or an expression there).
I suggest

    for (int : {1, 2, 3}) { ... }

or

    for (auto : {1, 2, 3}) { ... }

as being less likely to produce ambiguity, but just as good from the POV of avoiding unused variables.

Thanks for the observation that

    {
        lock_guard<mutex> lk(m);
        ...
    }

could also be written

    template<class T> class with;  // convert RAII class T into an iterable with one "element"

    for (auto lk : with<lock_guard<mutex>>(m)) {
        ...
    }

or, post-P0135,

    template<class T> auto with(T);

    for (auto lk : with(lock_guard<mutex>(m))) {
        ...
    }

or, post-a-proposal-in-which-the-name-of-an-otherwise-unused-loop-control-variable-may-be-omitted,

    template<class T> auto with(T);
    template<class M> auto with_lock(M);

    for (auto : with_lock(m)) {
        ...
    }

which is getting to be practically readable!

However, I admit that this might be a case of the good being the enemy of the perfect. I would hate to standardize this weird "for" hack, if there's a chance of one day standardizing the "with" keyword itself.

http://cplusplus.github.io/EWG/ewg-active.html#35 is IMHO talking about standardizing __COUNTER__ and/or __GUID__, which is a very good idea in its own right (much better than standardizing some weird interaction between short variable names and compiler diagnostics), but probably not useful for the lock_guard use-case.

–Arthur

Matthew Woehlke

unread,
Feb 22, 2016, 10:33:29 AM2/22/16
to std-pr...@isocpp.org
On 2016-02-20 20:12, Zhihao Yuan wrote:
> __ is a simple (maybe) solution, may have more uses, but I hope,
> in many cases, we can just let the C++ syntax itself not introducing
> a name from the beginning, and I think that's nicer.

That's what `__` *is*... it's a placeholder for 'not named'.

--
Matthew

Matthew Woehlke

unread,
Feb 22, 2016, 10:40:07 AM2/22/16
to std-pr...@isocpp.org
On 2016-02-21 08:55, Viacheslav Usov wrote:
> On Fri, Feb 19, 2016 at 9:06 PM, Patrice Roy wrote:
>> I often use _ as «uninteresting but needed» variables such as
>> lock_guards. Please don't break my code :)
>
> I would even say that this case, "uninteresting but needed" is more
> interesting. It would be nice to have a language construct that creates an
> "anonymous" variable in the current scope. Alternatively, this could be
> conceptualized as a temporary whose lifetime is extended till the end of
> the current scope.

Is that not what we're proposing?

--
Matthew

Viacheslav Usov

unread,
Feb 22, 2016, 12:00:36 PM2/22/16
to std-pr...@isocpp.org
I am not sure. The discussion definitely started with a very different idea, and I do not think I saw a clear statement similar to what I wrote above.

For the record, I dislike the special names that have been proposed. I believe the lifetime-extended temporary approach is more appropriate, so this should probably be phrased in a language involving temporaries; say if <expression> produces a temporary, then &<expression> makes it an anonymous variable (and an l-value) in the current scope. The use of & is just an example and not essential.

Cheers,
V.

Matthew Woehlke

unread,
Feb 22, 2016, 12:56:37 PM2/22/16
to std-pr...@isocpp.org
On 2016-02-22 12:00, Viacheslav Usov wrote:
> On Mon, Feb 22, 2016 at 4:35 PM, Matthew Woehlke wrote:
>> On 2016-02-21 08:55, Viacheslav Usov wrote:
>>> On Fri, Feb 19, 2016 at 9:06 PM, Patrice Roy wrote:
>>>> I often use _ as «uninteresting but needed» variables such as
>>>> lock_guards. Please don't break my code :)
>>>
>>> I would even say that this case, "uninteresting but needed" is
>>> more interesting. It would be nice to have a language construct
>>> that creates an "anonymous" variable in the current scope.
>>> Alternatively, this could be conceptualized as a temporary whose
>>> lifetime is extended till the end of the current scope.
>>
>> Is that not what we're proposing?
>
> I am not sure. The discussion definitely started with a very different
> idea, and I do not think I saw a clear statement similar to what I wrote
> above.

I'm not sure I'd call it "different" or not. The OP (who curiously seems
to have dropped out of the conversation) originally only mentioned being
implicitly `[[maybe_unused]]`. Ville immediately brought up
http://cplusplus.github.io/EWG/ewg-active.html#35, which dealt with
"nameless" variables, which seems consistent with the OP's intent as
well as much more useful (though Dmitry brings up the interesting point
that these should be `[[maybe_unused]]`, now that that seems likely to
be in C++17). I've generally read the rest of the thread as referring to
such 'anonymous variables'.

> For the record, I dislike the special names that have been proposed. I
> believe the lifetime-extended temporary approach is more appropriate, so
> this should probably be phrased in a language involving temporaries; say if
> <expression> produces a temporary, then &<expression> makes it an anonymous
> variable (and an l-value) in the current scope. The use of & is just an
> example and not essential.

I see at least one issue with that, namely that it doesn't solve the
OP's problem (anonymous variables as loop iterators). Otherwise, I fail
to see a semantic difference between:

&lock_guard{...}; // life extended until end of scope
auto&& . = lock_guard{...}; // anonymous variable

In both cases, a temporary that would otherwise be immediately destroyed
is lifetime-extended to the end of the scope in which the statement
appears. Said temporary is anonymous and cannot be named (i.e. used
again). The only difference I see¹ is syntactic.

Do I miss something?

(¹ Again, ignoring that reuse of declaration syntax means I can do
things with 'auto .' that I can't do with pure lifetime extension.)

Note also I'm not a big fan of changing the meaning of an existing
identifier, even `__`, to be something other than an identifier. That's
why I suggested using `.` instead; the proposed syntax is not (AFAIK)
currently legal, and `.` is definitely not an identifier.



Just for fun... here's how a potential 'do something X times' loop might
look in the future:

for (.: [0..X))
do_something();

(And no, this isn't completely theoretical code; it might well appear in
timing tests.)

--
Matthew

Thiago Macieira

unread,
Feb 22, 2016, 1:38:47 PM2/22/16
to std-pr...@isocpp.org
On segunda-feira, 22 de fevereiro de 2016 12:56:16 PST Matthew Woehlke wrote:
> for (.: [0..X))
> do_something();
>
> (And no, this isn't completely theoretical code; it might well appear in
> timing tests.)

With the potential of being O(n) in memory instead of O(1) if the compiler
doesn't optimise the intialiser list away.

Don't be lazy, just write:

for (int i = 0; i < X; ++i)

Dmitry Banschikov

unread,
Feb 22, 2016, 1:47:17 PM2/22/16
to std-pr...@isocpp.org
I haven't dropped conversation, just listening for opinions.
My initial desire was to have something like blank identifier in Go or _
variable in Python. Actually, I have got construct that works but looks ugly:
for(auto attempt [[gnu::unused]] : {1,2,3})
{
. . .
}

Possibly standard [[unused]] attribute specifier will make a sense.

The idea to have a "__" seems to me as orthogonal one(and for sure useful) and
having implicit unused attribute may be not appropriate for it.

Matthew Woehlke

unread,
Feb 22, 2016, 2:21:28 PM2/22/16
to std-pr...@isocpp.org
On 2016-02-22 13:38, Thiago Macieira wrote:
> On segunda-feira, 22 de fevereiro de 2016 12:56:16 PST Matthew Woehlke wrote:
>> for (.: [0..X))
>> do_something();
>>
>> (And no, this isn't completely theoretical code; it might well appear in
>> timing tests.)
>
> With the potential of being O(n) in memory instead of O(1) if the compiler
> doesn't optimise the intialiser list away.

Uh... no? There is no initializer list in the above. That's a P0268
up-to expression; P0268 is quite clear¹ that the memory use is O(1).
(Likewise for my indexrange library version... and the underlying
implementation is likely very similar between the two.)

(¹ "The memory usage of `[a..b)` is proportional to `make_pair(a,b)`,
not an array of length b–a." "Note that this example [...] does not
store 1,000,000 `int`s at any time.")

--
Matthew

Matthew Woehlke

unread,
Feb 22, 2016, 2:35:39 PM2/22/16
to std-pr...@isocpp.org
On 2016-02-22 13:47, Dmitry Banschikov wrote:
> I haven't dropped conversation, just listening for opinions.
> My initial desire was to have something like blank identifier in Go or _
> variable in Python.

That sure *sounds* like what we're discussing :-). (But then, I'm not
familiar with either of those...)

> Actually, I have got construct that works but looks ugly:
> for(auto attempt [[gnu::unused]] : {1,2,3})
> {
> . . .
> }
>
> Possibly standard [[unused]] attribute specifier will make a sense.

That's P0068/P0212 (http://wg21.link/p0212).

The problem - as most of us are viewing it - with the above is you still
have to name the variable :-).

> The idea to have a "__" seems to me as orthogonal one (and for sure useful) and
> having implicit unused attribute may be not appropriate for it.

Well... yes and no. We're likely to get `[[maybe_unused]]` in C++17. I
don't see where you'd want an anonymous variable to *not* have that
attribute, though. After all, it is *necessarily* unused, since you
can't name it...

So... not *quite* orthogonal, but the dependency is only at the QoI
level and only in one direction.

To be clear: I think we mostly¹ agree that we'd like both features;
we're just arguing about the implementation details :-).

One thing I think we *don't* want is to merely apply `[[maybe_unused]]`
to one or more specific identifiers (e.g. `_`). That seems silly. But we
want (and seem likely to get) the attribute, and we (most of us anyway)
also want the ability to declare anonymous variables.

(¹ See Viacheslav Usov's most recent post re: lifetime extension for a
contrary opinion - so far, the only one expressed in this thread.)

I would encourage you or someone to write a paper. I'll even offer to
help. (I'd write it myself, I just don't want to do it right now. If no
one else does, I may write it in a few months.) It's definitely not a
crazy idea and seems like it has decent hope for being accepted.

--
Matthew

Dmitry Banschikov

unread,
Feb 22, 2016, 2:57:52 PM2/22/16
to std-pr...@isocpp.org
OK, I will try it. I will contact you off the list for details.
Thank you!



--

Dmitry Banschikov

Thiago Macieira

unread,
Feb 22, 2016, 4:09:13 PM2/22/16
to std-pr...@isocpp.org
On segunda-feira, 22 de fevereiro de 2016 14:21:12 PST Matthew Woehlke wrote:
> Uh... no? There is no initializer list in the above. That's a P0268
> up-to expression; P0268 is quite clear¹ that the memory use is O(1).
> (Likewise for my indexrange library version... and the underlying
> implementation is likely very similar between the two.)

Ah, I see. I haven't read P0268 yet.

I don't think I like the language change. If it can be done in a library, it
should be done in the library. indexrange is better.

Matthew Woehlke

unread,
Feb 22, 2016, 4:40:01 PM2/22/16
to std-pr...@isocpp.org
On 2016-02-22 16:09, Thiago Macieira wrote:
> On segunda-feira, 22 de fevereiro de 2016 14:21:12 PST Matthew Woehlke wrote:
>> Uh... no? There is no initializer list in the above. That's a P0268
>> up-to expression; P0268 is quite clear¹ that the memory use is O(1).
>> (Likewise for my indexrange library version... and the underlying
>> implementation is likely very similar between the two.)
>
> Ah, I see. I haven't read P0268 yet.
>
> I don't think I like the language change. If it can be done in a library, it
> should be done in the library. indexrange is better.

Hehe... :-) I'd love to see P0268, but I'm inclined to agree. That's one
of a couple points I have regarding the paper that I intend to bring up
when it's presented.

--
Matthew

Tony V E

unread,
Feb 22, 2016, 5:21:49 PM2/22/16
to Matthew Woehlke
For the issues of backwards compatibility, I think we could use _ (single) with just the additional rule that _ can be used to name more than one variable per scope. So

void f()
{
auto _ = lock_guard(...); // OK today
auto _ = foo(); // OK, becomes anonymous 
...
for (int _ : {0,1,2,3})  // OK today
 cout << _; // uses inner scope _

cout << _; // Error - ambiguous use of _


‎So if anyone is currently using _ as a variable name - even beyond just construction, it still works. 



Sent from my BlackBerry portable Babbage Device
  Original Message  
From: Matthew Woehlke
Sent: Monday, February 22, 2016 4:39 PM
To: std-pr...@isocpp.org
Reply To: std-pr...@isocpp.org
Subject: [std-proposals] Re: throwaway variable
--
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/nafv75%24r8v%241%40ger.gmane.org.

Moritz Klammler

unread,
Feb 22, 2016, 6:32:24 PM2/22/16
to std-pr...@isocpp.org
I'm excited that this is getting attention because I was thinking about
proposing a feature for this, too.

I don't think that macro magic like `__COUNTER__` that was mentioned by
somebody is a solution. It is too cumbersome in header files due to
potential ODR violations.

My preferred syntax for such a variable would be to simple not give it a
name.

auto /* anonymous */ = std::unique_lock<std::mutex> { ... };

We could have any number of them in a scope.

auto = finally {[](){ std::cout << "I'm done!\n"; }};
auto = 42; // pointless but valid, it's a different variable

This would be consistent with (default) parameters in templates and
functions.

template <typename, typename = int>
void foo(double, std::string = "anonymous");

I'm not sure whether extending this to concrete types (rather than
`auto`) would be desirable.

finally = [](){ std::cout << "I'm really done!\n"; }; // looks cute
int = 42; // still valid, still pointless

For a start, I'd recommend against it. It can always be added later.

The only problem with this syntax is that it doesn't work with
non-move types. Unfortunately, those are notoriously frequent
candidates for anonymous scoped variables, think `std::lock_guard`.

The analogue syntax using direct initialization

std::lock_guard<std::mutex> /* anonymous */ { ... };

is already taken and creates a temporary object...

Fortunately, there is a proposal (I don't know the number off the top of
my head) to make copy elision mandatory in some cases so "always almost
auto" could become "always auto". If this were accepted, I think that
the described syntax would be a powerful yet easy to understand
solution.

Otherwise, we might absuse the `auto` keyword.

auto auto = 42;
int auto = 42;
std::lock_guard<std::mutex> auto { ... };

Not that pretty but possibly doable.

If somebody is about to write a proposal, I'd be happy to contribute.


Tony V E <tvan...@gmail.com> writes:

> For the issues of backwards compatibility, I think we could use _
> (single) with just the additional rule that _ can be used to name more
> than one variable per scope. So
>
> void f()
> {
> auto _ = lock_guard(...); // OK today
> auto _ = foo(); // OK, becomes anonymous
> ...
> for (int _ : {0,1,2,3}) // OK today
> cout << _; // uses inner scope _
>
> cout << _; // Error - ambiguous use of _
>
>
> ‎So if anyone is currently using _ as a variable name - even beyond
> just construction, it still works.
--
OpenPGP:

Public Key: http://openpgp.klammler.eu
Fingerprint: 2732 DA32 C8D0 EEEC A081 BE9D CF6C 5166 F393 A9C0

Tony V E

unread,
Feb 22, 2016, 6:46:49 PM2/22/16
to Moritz Klammler
Note that use of _ would also work well with s‎tructured bindings:

auto { x, _, _, w} = getthing();

(although you may or may not want/expect lifetime extension here)

Sent from my BlackBerry portable Babbage Device
  Original Message  
From: Moritz Klammler
Sent: Monday, February 22, 2016 6:32 PM
Subject: Re: [std-proposals] Re: throwaway variable
--
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/87io1gtj7g.fsf%40gmail.com.

Patrice Roy

unread,
Feb 22, 2016, 7:27:43 PM2/22/16
to std-pr...@isocpp.org
The «can use more than once in a scope» is an interesting twist. If that doesn't cause too many problems with existing code (such as people accessing members of _ afterwards), it could be an interesting language-supported idiom. Does anyone have any idea whether people actually write such things as «auto _ = string{"Hi"}; auto n = _.size(); /* evil distilled */»? If it's not common practice (which I sincerely hope, but can in no way guarantee), we might have something...

Tony V E

unread,
Feb 22, 2016, 7:30:38 PM2/22/16
to Patrice Roy
Even if code currently does that, we are still fine.

It is only once you add the second _ in the same scope as the first *then* _.size() will start to fail. 

Which is fine. Don't do that.


Sent from my BlackBerry portable Babbage Device
From: Patrice Roy
Sent: Monday, February 22, 2016 7:27 PM

Viacheslav Usov

unread,
Feb 23, 2016, 7:00:41 AM2/23/16
to std-pr...@isocpp.org
On Mon, Feb 22, 2016 at 8:35 PM, Matthew Woehlke <mwoehlk...@gmail.com> wrote:
 
(¹ See Viacheslav Usov's most recent post re: lifetime extension for a
contrary opinion - so far, the only one expressed in this thread.)

I do not think I said anything really contrarian. I definitely do see a need for anonymous variables; the interpretation as a lifetime extension of temporaries is secondary.

I am leaning toward lifetime extension because that could be made syntactically an expression, which has a value (l-value), which can be used in a greater expression, thus making it possible to refer to the otherwise inaccessible variable.

With respect to anonymous looping variables, frankly, I do not think I have ever missed them, but that may be just me.

Cheers,
V.

Matthew Woehlke

unread,
Feb 23, 2016, 9:57:05 AM2/23/16
to std-pr...@isocpp.org
On 2016-02-23 07:00, Viacheslav Usov wrote:
> On Mon, Feb 22, 2016 at 8:35 PM, Matthew Woehlke wrote:
>
>> (¹ See Viacheslav Usov's most recent post re: lifetime extension for a
>> contrary opinion - so far, the only one expressed in this thread.)
>
> I do not think I said anything really contrarian. I definitely do see a
> need for anonymous variables; the interpretation as a lifetime extension of
> temporaries is secondary.
>
> I am leaning toward lifetime extension because that could be made
> syntactically an expression, which has a value (l-value), which can be used
> in a greater expression, thus making it possible to refer to the otherwise
> inaccessible variable.

Oh, okay, now I understand. Thanks for clarifying.

Maybe we do need both. Do you have an example of such an expression
"used in a greater expression"?

> With respect to anonymous looping variables, frankly, I do not think I have
> ever missed them, but that may be just me.

Sure... I feel somewhat confident that I could have used them at least a
few times, but they're definitely less common¹. It's more that they do
have potential, and fall out as a natural consequence ("for free", if
you will) of using a variable-declaration syntax.

(¹ I am confident I could find at least a half dozen instances where I
could use an anonymous variable / lifetime extended temporary in less
than five minutes, whereas I know I'd have to look hard for where I
might use an anonymous loop variable. Of course, everyone "knows" that
just about any "scoped guard" - of which I could name several offhand -
would typically benefit...)

--
Matthew

Matthew Woehlke

unread,
Feb 23, 2016, 10:00:07 AM2/23/16
to std-pr...@isocpp.org
On 2016-02-22 17:21, Tony V E wrote:
> For the issues of backwards compatibility, I think we could use _
> (single) with just the additional rule that _ can be used to name
> more than one variable per scope. [...]
>
> ‎So if anyone is currently using _ as a variable name - even beyond
> just construction, it still works.

Besides that I dislike that that's now a "magic identifier", what about
*functions* named `_`?

I'd really prefer `.`... what's wrong with `.`? No one has discussed
that except a vague impression that it's not liked, but no one has said
why...

--
Matthew

Matthew Woehlke

unread,
Feb 23, 2016, 10:10:22 AM2/23/16
to std-pr...@isocpp.org
On 2016-02-22 18:32, Moritz Klammler wrote:
> I'm excited that this is getting attention because I was thinking about
> proposing a feature for this, too.
>
> I don't think that macro magic like `__COUNTER__` that was mentioned by
> somebody is a solution. It is too cumbersome in header files due to
> potential ODR violations.
>
> My preferred syntax for such a variable would be to simple not give it a
> name.
>
> auto /* anonymous */ = std::unique_lock<std::mutex> { ... };

That's the idea behind using `.`... `.` is not a name, but it's a
syntactic placeholder. My concern with omitting *any* name (or
placeholder) is that there may be syntactic ambiguities that arise as a
result.

> This would be consistent with (default) parameters in templates and
> functions.
>
> template <typename, typename = int>
> void foo(double, std::string = "anonymous");

Why is that valuable? I don't see how the two are related.

> The only problem with this syntax is that it doesn't work with
> non-move types.

Um... `auto&& . = not_movable{};`? Works AFAIK. (Does need the `&&`, but
that doesn't strike me as a deal-breaker.)

--
Matthew

Patrik

unread,
Feb 23, 2016, 10:24:49 AM2/23/16
to ISO C++ Standard - Future Proposals
If you guys are proposing to add special case syntax rule to the language for "_" variable names. Why not try and make the rule and feature a bit more general? So it not only support unique variable name generation/substitution, but also supports user configurable (compile time) name substitution. That way we might get rid of another use case for unsafe preprocessor macros.

Example for unique name generation and substitution might look something like this:

int __SubstituteName("")__ = 2; //if param is an empty str then compiler generate a unique one.

for(auto __SubstituteName("")__ : {1, 2, 3}) {}

std::lock_guard<std::mutex> __SubstituteName("")__(m);

Example for user configured name substitution might look something like this:

int mycounter = 0;
static_string name = "mycounter";
__SubstituteName(name)__ = 1;
__SubstituteName(name)__++;
assert(__SubstituteName(name)__==2);

Such a feature might with a bit of imagination (and magic) help in de-serialization of a compile time string into a generated struct.

stuct __GetName(meta.name)__{
typename meta.vars[1].type __SubstituteName(meta.vars[1].name)__;
typename meta.vars[2].type __SubstituteName(meta.vars[2].name)__;
typename meta.vars[3].type __SubstituteName(meta.vars[3].name)__;
//...
};

It should probably play nice with the static reflection proposal. I'm not familiar with it, but surely it uses somekind of static_string type one could use.

Just my 2 cents. I haven't thought this through much though.

Regards /Petke

Viacheslav Usov

unread,
Feb 23, 2016, 10:28:09 AM2/23/16
to std-pr...@isocpp.org
On Tue, Feb 23, 2016 at 3:56 PM, Matthew Woehlke <mwoehlk...@gmail.com> wrote:

> Do you have an example of such an expression "used in a greater expression"?

Assuming that the lifetime-extending syntax is @ in front of a temporary:

{
    auto ptr = (@std::string("hello")).c_str(); // ptr is valid till the end of the scope
}

Cheers,
V.

Matthew Woehlke

unread,
Feb 23, 2016, 10:41:53 AM2/23/16
to std-pr...@isocpp.org
On 2016-02-23 10:28, Viacheslav Usov wrote:
> On Tue, Feb 23, 2016 at 3:56 PM, Matthew Woehlke wrote:
>> Do you have an example of such an expression "used in a greater
>> expression"?
>
> Assuming that the lifetime-extending syntax is @ in front of a temporary:
>
> {
> auto ptr = (@std::string("hello")).c_str(); // ptr is valid till the
> end of the scope
> }

Aah...

...wasn't there a proposal floating around to do that automatically,
though? (Maybe annotating it is easier?)

--
Matthew

Viacheslav Usov

unread,
Feb 23, 2016, 10:49:22 AM2/23/16
to std-pr...@isocpp.org
On Tue, Feb 23, 2016 at 4:41 PM, Matthew Woehlke <mwoehlk...@gmail.com> wrote:

> ...wasn't there a proposal floating around to do that automatically, though?

I am not aware of a such a proposal; any pointers?

If that proposal pins a temporary to the scope when it is used in some particular way, then perhaps it would be equivalent. But then one of those "particular ways" should include something that the equivalent of

{
    @std::lock_guard(mutex);
    // do things
}

were easily expressible.

Cheers,
V.

Matthew Woehlke

unread,
Feb 23, 2016, 11:04:04 AM2/23/16
to std-pr...@isocpp.org, pot...@gmail.com
On 2016-02-23 10:49, Viacheslav Usov wrote:
> On Tue, Feb 23, 2016 at 4:41 PM, Matthew Woehlke wrote:
>> ...wasn't there a proposal floating around to do that automatically,
>> though?
>
> I am not aware of a such a proposal; any pointers?

http://wg21.link/n4221 ...and you may want to ping David Krauss (CC'd)
as to what ever happened with it, as I don't recall offhand.

> If that proposal pins a temporary to the scope when it is used in some
> particular way, then perhaps it would be equivalent. But then one of those
> "particular ways" should include something that the equivalent of
>
> {
> @std::lock_guard(mutex);
> // do things
> }
>
> were easily expressible.

I don't think it tried to cover this; only where the entity was still
accessible, albeit indirectly or only partially.

--
Matthew

Viacheslav Usov

unread,
Feb 23, 2016, 11:43:25 AM2/23/16
to std-pr...@isocpp.org, pot...@gmail.com
On Tue, Feb 23, 2016 at 5:03 PM, Matthew Woehlke <mwoehlk...@gmail.com> wrote:

> I don't think it tried to cover this; only where the entity was still accessible, albeit indirectly or only partially.

It would be nice to know where that proposal stands, certainly.

Even if it gets adopted, though, I'd say an explicit lifetime extension syntax is not useless. As far as I can tell, the proposal essentially depends on propagating lifetime extension via export-decorated functions. That takes an effort, and there is legacy/library code, too, so pinning a temporary explicitly can just be easier. And it solves the anonymous variable problem, too.

Cheers,
V.

Moritz Klammler

unread,
Feb 23, 2016, 2:56:18 PM2/23/16
to std-pr...@isocpp.org
Matthew Woehlke <mwoehlk...@gmail.com> writes:

> On 2016-02-22 18:32, Moritz Klammler wrote:
>> I'm excited that this is getting attention because I was thinking about
>> proposing a feature for this, too.
>>
>> I don't think that macro magic like `__COUNTER__` that was mentioned by
>> somebody is a solution. It is too cumbersome in header files due to
>> potential ODR violations.
>>
>> My preferred syntax for such a variable would be to simple not give it a
>> name.
>>
>> auto /* anonymous */ = std::unique_lock<std::mutex> { ... };
>
> That's the idea behind using `.`... `.` is not a name, but it's a
> syntactic placeholder. My concern with omitting *any* name (or
> placeholder) is that there may be syntactic ambiguities that arise as a
> result.

I understand that but I'd prefer if we culd do without adding yet
another magic token. `...` is already heavily used (and yet quite
consistently). `.` might be a smart trick, although a little too smart
for my taste. `_` and `__` have already been discussed at length
before. In particular, I wouldn't like special-casing along the lines
of "if the identifier is defined more than once, magic happens". But I
think we have agreement here.

>> This would be consistent with (default) parameters in templates and
>> functions.
>>
>> template <typename, typename = int>
>> void foo(double, std::string = "anonymous");
>
> Why is that valuable? I don't see how the two are related.

Well, I don't have a mathematical proof for my stylistic preferences but
isn't it the case that in

static std::mutex mtx {}; // global variable

void
synchronized(const std::string& msg,
std::unique_lock<std::mutex> = std::unique_lock<std::mutex> {mtx})
{
std::cout << msg << std::endl;
}

we basically have the same thing as we would have in

void
synchronized(const std::string& msg)
{
static std::mutex mtx {};
auto = std::unique_lock<std::mutex> {mtx};
std::cout << msg << std::endl;
}

would the syntax be allowed?

It's not exactly the same because the parameter is constructed before
the function body is entered and the anonymous scoped variable in the
body is only created after that but from the user's point of view, I see
many parallels.

Most fundamentally, in both cases we want to have a variable with a
certain value and well-defined life-time but don't bother giving it a
name because we never access it again.

And because the syntax

<type> [ <identifier> ] [ '=' <expression> ]

is already used elsewhere, it would seem natural and easy-to-explain to
me if we would re-use it here.

Thiago Macieira

unread,
Feb 23, 2016, 6:37:46 PM2/23/16
to std-pr...@isocpp.org
On terça-feira, 23 de fevereiro de 2016 07:24:48 PST Patrik wrote:
> It should probably play nice with the static reflection proposal. I'm not
> familiar with it, but surely it uses somekind of static_string type one
> could use.

Not in the way you're talking about.

Reflection is about obtaining information about types that exist, not about
modifying them or generating code.

snk_kid

unread,
Feb 24, 2016, 11:31:54 AM2/24/16
to ISO C++ Standard - Future Proposals
I think we will need something like this for sure if C++ continues expanding on (more) pattern matching functionality, in particular "structural bindings" and case/match expressions, especially with nested-patterns. In other languages with pattern matching support _ is usually called a wildcard (binding) pattern and means to "match anything". In those languages _ isn't a variable and I don't think it's a good idea to be standardized as a variable, I think it should be part of the syntax sub-grammars for pattern-expressions. If that's not possible due to conflicts with existing code that has _ variables then use another symbol?

On Friday, February 19, 2016 at 8:05:04 PM UTC, Dmitry Banshchikov wrote:
Hi!

Does anyone see helpfulness of such solution:

for(auto _ : {1, 2, 3})
{
}

Variable with name "_" has an implicit unused attribute set.


-- 

Dmitry Banschikov

Thiago Macieira

unread,
Feb 24, 2016, 3:01:40 PM2/24/16
to std-pr...@isocpp.org
On quarta-feira, 24 de fevereiro de 2016 08:31:53 PST 'snk_kid' via ISO C++
Standard - Future Proposals wrote:
> If that's not possible due to
> conflicts with existing code that has _ variables then use another symbol?

It's about 40 years too late to change the meaning of _. Using other symbols
has the problem that we're out of characters from the basic character set.

The symbol characters allowed are:

_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " ’

All of those are already in use.

We'd need a compound identifier (more than one character), like digraphs do.

Tom Honermann

unread,
Feb 24, 2016, 4:10:04 PM2/24/16
to std-pr...@isocpp.org
On 2/24/2016 3:01 PM, Thiago Macieira wrote:
> On quarta-feira, 24 de fevereiro de 2016 08:31:53 PST 'snk_kid' via ISO C++
> Standard - Future Proposals wrote:
>> If that's not possible due to
>> conflicts with existing code that has _ variables then use another symbol?
> It's about 40 years too late to change the meaning of _. Using other symbols
> has the problem that we're out of characters from the basic character set.
>
> The symbol characters allowed are:
>
> _ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " ’
>
> All of those are already in use.
>
> We'd need a compound identifier (more than one character), like digraphs do.
>
Or we add @ or $ or ` or ... to the basic source character set :)

Tom.

David Krauss

unread,
Feb 25, 2016, 11:25:33 AM2/25/16
to Matthew Woehlke, ISO C++ Standard - Future Proposals
On 2016–02–24, at 12:03 AM, Matthew Woehlke <mwoehlk...@gmail.com> wrote:

On 2016-02-23 10:49, Viacheslav Usov wrote:
On Tue, Feb 23, 2016 at 4:41 PM, Matthew Woehlke wrote:
...wasn't there a proposal floating around to do that automatically,
though?

I am not aware of a such a proposal; any pointers?

http://wg21.link/n4221 ...and you may want to ping David Krauss (CC'd)
as to what ever happened with it, as I don't recall offhand.

The EWG consensus on N4221 was that it didn’t support generic programming well enough. I revised it as P0066R0, but that was found to be too complicated, and also too open-ended for the included analysis.

I hope to revise it eventually, but it has some distance to go. In particular, there are too many manual annotations required. It would be better to annotate classes that are iterators, containers, views, etc., and then functions would adjust automatically.

A prototype is available at https://github.com/potswa/clang/tree/lifetime_extension. It works up to conversions (casts) between the new function types, and automatic annotation of implicitly-declared members. (I should add some documentation!) Since the feature is intended to be open-ended, and the analysis in P0066R0 is already voluminous, significant field testing and user testimonials would need to happen before it could go back to ISO.

If that proposal pins a temporary to the scope when it is used in some
particular way, then perhaps it would be equivalent. But then one of those
"particular ways" should include something that the equivalent of

{
   @std::lock_guard(mutex);
   // do things
}

were easily expressible.

I don't think it tried to cover this; only where the entity was still
accessible, albeit indirectly or only partially.

Right. Actually, immediately before N4221, I presented another proposal about scope guards, N4149. It annotated such classes with &, where && was given some “opposite” meaning. EWG was open to annotating guard classes and suggested to split and specialize that aspect.

A guard class always instantiates a guard variable, and that’s why anonymity works for them. So, I think decorating the class should work well, and we might not need anonymous variables of other arbitrary types.

Nicol Bolas

unread,
Feb 25, 2016, 9:24:58 PM2/25/16
to ISO C++ Standard - Future Proposals


On Wednesday, February 24, 2016 at 3:01:40 PM UTC-5, Thiago Macieira wrote:
On quarta-feira, 24 de fevereiro de 2016 08:31:53 PST 'snk_kid' via ISO C++
Standard - Future Proposals wrote:
> If that's not possible due to
> conflicts with existing code that has _ variables then use another symbol?

It's about 40 years too late to change the meaning of _. Using other symbols
has the problem that we're out of characters from the basic character set.

The symbol characters allowed are:

_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " ’

All of those are already in use.

We'd need a compound identifier (more than one character), like digraphs do.

Do we? What are the syntactic issues around making this work:

auto = <insert expression here>;

Note that I'm being as conservative as possible here. It would only be allowed for `auto` (or `decltype(auto)` perhaps?), and you could only declare one such variable at a time.

It's not an ideal syntax, but I think it's workable given the problem domain.

Viacheslav Usov

unread,
Feb 26, 2016, 7:38:47 AM2/26/16
to std-pr...@isocpp.org, Matthew Woehlke, David Krauss
On Thu, Feb 25, 2016 at 5:25 PM, David Krauss <pot...@gmail.com> wrote:

> Right. Actually, immediately before N4221, I presented another proposal about scope guards, N4149. It annotated such classes with &, where && was given some “opposite” meaning. EWG was open to annotating guard classes and suggested to split and specialize that aspect.

A problem with that approach is that the semantics of, e.g., std::lock_guard(mutex), will be very different (correct or seriously flawed) depending on what implementation is being used. With the pretty much unavoidably uneven state of the field, that is dangerous. But that's always the case with semantics changing silently and profoundly, so it is surprising EWG was so relaxed about that.

Cheers,
V.

Moritz Klammler

unread,
Feb 26, 2016, 8:42:11 AM2/26/16
to std-pr...@isocpp.org
Nicol Bolas <jmck...@gmail.com> writes:

> [...]
>
> Do we? What are the syntactic issues around making this work:
>
> auto = <insert expression here>;
>
> Note that I'm being as conservative as possible here. It would *only*
> be allowed for `auto` (or `decltype(auto)` perhaps?), and you could
> only declare one such variable at a time.
>
> It's not an ideal syntax, but I think it's workable given the problem
> domain.

As mentioned earlier, this would be my preferred syntax, too. I
actually believe it *would* be "ideal". If you don't want to name a
thing -- just don't give it a name. Same as with parameter
declarations.

David Krauss

unread,
Feb 26, 2016, 9:32:03 AM2/26/16
to Viacheslav Usov, ISO C++ Standard - Future Proposals, Matthew Woehlke
I don’t quite follow. In this case, std::lock_guard would be annotated, for example,

template <class... MutexTypes>
class lock_guard guard { // contextual keyword
    …
};

Then the user would be free to simply omit the declarator:

std::mutex m;
void foo() {
    std::lock_guard( m ); // expression-statement comprising a conversion expression
    do_something();
    do_next_thing();
    // release lock.
}

The benefit is that the common mistake is restored to correct working order.

Do you mean that this would be dangerous with user-defined guards?

std::mutex m;
template< typename locker >
void foo() {
    locker( m ); // idiomatic
    do_something();
    do_next_thing();
    // release lock.
}

void bar() {
    foo< old_library::custom_lock >(); // Danger!
}

Indeed, the flip side of blessing any common lazy error is that everyone will start doing it.

If this is what you mean, it implies that an opt-in is necessary. I don’t think any opt-in solution is worth the effort, because if I can remember to use the anonymizing feature,  then I can remember to name the variable. 99% of guards do not share their scope with another guard, and so they can all be named guard.

It happens that guards are often generated by macros, but then you can always get a unique name like MY_LIB_GUARD##__LINE__. Ugly perhaps, but it’s uniform with what macros ordinarily do. The corner cases left behind are minuscule. (And just to be clear, you don’t need this unless you’re already inside a macro definition.)

Checking EWG 35, its motivation is also generating multiple guard variables on a single line from a macro. Just my 2¢, I guess, but while macro hacks are bad, macro catenation isn’t really a hack if you’re already inside a macro. The naming convention used by a macro is at least somewhat meaningful, and pulling names out of thin air could make it totally impossible to figure out the provenance of an anonymous variable.

A preprocessor-like feature baked into the core language is still as bad as (even worse than) using the preprocessor.

Viacheslav Usov

unread,
Feb 26, 2016, 9:53:14 AM2/26/16
to David Krauss, ISO C++ Standard - Future Proposals, Matthew Woehlke
On Fri, Feb 26, 2016 at 3:31 PM, David Krauss <pot...@gmail.com> wrote:

> Do you mean that this would be dangerous with user-defined guards?

That too, but I am more concerned about things like std::lock_guard that in today's implementations would normally need to be used as

{
    lock_guard lg(mutex);
    // ...
}

When it becomes possible to use them as

{
    lock_guard(mutex);
    // ...
}

They will get used as such, but then if the code using them migrates to the old (today's) implementations, it will become silently broken. In the particular case of locking, breakage can easily make it into production, when everything works most of the time, but misbehaves sometimes, and it is about impossible to repro and debug that.

An opt-in seems definitely in order, and, as you say, it's worthwhile only if it is more trivial in use than the current practice. Something like a new postfix expression extending the lifetime of a temporary could do it.

Cheers,
V.

T. C.

unread,
Feb 26, 2016, 12:07:46 PM2/26/16
to ISO C++ Standard - Future Proposals, pot...@gmail.com, mwoehlk...@gmail.com
Assuming that lock_guard is a type, `lock_guard(mutex);` is a declaration of a lock_guard called 'mutex' (which is error because you can't default-construct a lock_guard). 

If you want this to work, you'll have to change the disambiguation rule too.

David Krauss

unread,
Feb 26, 2016, 8:11:59 PM2/26/16
to std-pr...@isocpp.org
On 2016–02–27, at 1:07 AM, T. C. <rs2...@gmail.com> wrote:

Assuming that lock_guard is a type, `lock_guard(mutex);` is a declaration of a lock_guard called 'mutex' (which is error because you can't default-construct a lock_guard). 

If you want this to work, you'll have to change the disambiguation rule too.

Yeah. Tricky, but doable. At least the parser has the benefit of having seen the decl-specifier-seq, so it can look up std::lock_guard. If that names a complete guard class type, then don’t parse parentheses in the declarator. (And of course that’s a breaking change for existing declarations like std::lock_guard (guard)( m );. A proposer might try to convince EWG that such things don’t exist in practice.)

Jean-Marc Bourguet

unread,
Feb 29, 2016, 6:55:08 AM2/29/16
to ISO C++ Standard - Future Proposals
I'm pretty sure I've seen that used in C for simple functions for which a macro equivalent is also provided for performance purpose.  Obviously in C++ inline is a far better solution, but I'd be surprised if there no such code existed in the wild, for instance having survived a conversion from C with nobody taking the pain to rewrite something which worked.

Yours,

-- 
Jean-Marc

David Krauss

unread,
Mar 4, 2016, 4:54:34 AM3/4/16
to std-pr...@isocpp.org
Certainly parenthesized declarator-ids have a time and place. It just doesn’t intersect with scope guard usage.


Reply all
Reply to author
Forward
0 new messages