Anonymous variables (moved "deferred destruction" topic)

449 views
Skip to first unread message

Francisco Lopes

unread,
Jul 10, 2016, 1:37:01 PM7/10/16
to ISO C++ Standard - Future Proposals
I'm moving the "deferred destruction" topic here to make things clearer.

The current proposal idea I'm moving forward with allowing (semi) anonymous variables.
The idea is to adopt _ as a special variable name that supports overriding, but in a backwards
compatible way:

  • _ should be allowed as a variable name.
  • _ should be allowed in redeclarations, overriding the previous declaration in the same scope.
This special variable would, for example, improve usage of:
  • any kind of guards, like std::lock_guard for example
  • multiple return (P0217R2)
  • scope_exit (P0052R2)

Here's some example code showing these features:


#include <mutex>
#include <tuple>
#include <scope>
#include <thread>
#include <memory>
#include <iostream>

using namespace std;

mutex m1, m2;

tuple<int, int> divide(int dividend, int divisor) {
    return  make_tuple(dividend / divisor, dividend % divisor);
}

int main() {
    auto _ = make_scope_exit([]{ cout << " bye"; }); // no need to care about scope_exit naming
    auto _ = make_scope_exit([]{ cout << "bye"; });  // _ is the only variable name that supports being overriding
    lock_guard<mutex> _(m1), _(m2);                  // it always refers to the last declaration in the current scope
    auto [_, remainder] = divide(14, 3);             // works on multiple return
}


Thanks Tony V E for the input in the previous thread.

Tony V E

unread,
Jul 10, 2016, 1:52:54 PM7/10/16
to Standard Proposals
I think "last declaration" is somewhat good for:

    Foo _{ 1, 2, 3 };
    _.setX(4); // unfortunately not available via constructor
    Foo _{ 5, 6, 7 };
    _.setX(8);

But I worry about cases like:

    // currently valid code
    Foo _{1,2,3};
    _.use();
    more();
    code();
    if (lots())
       of();
    else
      code();
    code();
    code();
    code();
    _.use_again();

And then someone copy-pastes another _ snippet in the middle.

    // currently valid code
    Foo _{1,2,3};
    _.use();
    more();
    code();
    if (lots())
       of();
    else
      code();
    Foo _{5,6,7};
    code();
    code();
    code();
    _.use_again();

Particularly when '_.use_again()' is '_.unlock()' on a scope-guard.

Of course, anyone who is currently using _ as a variable name AND is using it throughout their function, probably has other problems.

But I can imagine code that was using _ as a lock guard, then later someone realized that the guard should unlock early, so just added a _.unlock() without renaming the variable.

And then, later, the code evolves some more and another _ is added in the middle.

That is, unfortunately, how code is written.

Tony




--
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/505fe073-a45b-4974-b1cb-df03ea39a5c6%40isocpp.org.

Francisco Lopes

unread,
Jul 10, 2016, 2:09:37 PM7/10/16
to ISO C++ Standard - Future Proposals
Thanks for the input again. Well that's an awful sample of bad practices, I agree with your point
though. So, between overring with accessibility vs overrinding disallowing accessibility, I'm left
in doubt which is nicer.

In any case I'd advocate that _.foo() should be frowned upon always.

Regards

Brandon Kentel

unread,
Jul 10, 2016, 2:39:07 PM7/10/16
to ISO C++ Standard - Future Proposals
Isn't _ typically / often used as alias for GNU gettext()? This could cause some resistance to the proposal as it is (regardless of how bad -- though convenient -- a choice it was to use this alias). Maybe it could be dealt with by treating this as a special case in the grammar? Again, likely to meet some resistance. Maybe reuse the now defunct register keyword /s ?

Patrice Roy

unread,
Jul 10, 2016, 2:39:42 PM7/10/16
to std-pr...@isocpp.org
One could envision "fun" things such as :

int _ = 3;
auto _ = _; // code maintenance just became even more frightening

An idea would be to make use of _ incorrect past initialization, such that the use of _ on the right hand would not compile, but I guess someone could want to use _ as a way to avoid caring about a pass-by-reference argument in some function :

pair<string,float> fct(int);
void f(int &, int&);
auto g() {
   int x = 3;
   auto _ = ""; // useless but would be legal
   auto [s,_] = fct(x); // fair enough, can live with this...
   f(x, _); // don't care about the 2nd argument... this seems like a legitimate use case, I guess, but f(_,_) and other unusual things become possible...
   return x + s.size();
}

I'm not totally against this feature, but it deserves detailed scrutiny before moving ahead...



Francisco Lopes

unread,
Jul 10, 2016, 2:51:24 PM7/10/16
to ISO C++ Standard - Future Proposals, bke...@gmail.com
Initially I was thinking about using ... instead of _ to avoid such naming issue. If adopting ...
as the placeholder, then I'd go for it not being referenciable at all, and would touch the current
usage of _.

Personally I'm open to such changes because I'm caring more for the core functionality.

Francisco Lopes

unread,
Jul 10, 2016, 2:54:18 PM7/10/16
to ISO C++ Standard - Future Proposals, bke...@gmail.com
woudn't touch*

Ville Voutilainen

unread,
Jul 10, 2016, 2:55:22 PM7/10/16
to ISO C++ Standard - Future Proposals
On 10 July 2016 at 21:51, Francisco Lopes
<francisco.m...@oblita.com> wrote:
> Initially I was thinking about using ... instead of _ to avoid such naming
> issue. If adopting ...

Don't go there, that idea clashes badly with packs.

Also, this is https://cplusplus.github.io/EWG/ewg-active.html#35

Francisco Lopes

unread,
Jul 10, 2016, 3:14:39 PM7/10/16
to ISO C++ Standard - Future Proposals
Many thanks for that reference Ville. I see there was invitation for a paper, but
no more information about it going forward, is there anything going forward already?

I think as demonstrated, with the current and future additions to the standard,
more usecases are showing up in favor of such feature.

Ville Voutilainen

unread,
Jul 10, 2016, 3:19:29 PM7/10/16
to ISO C++ Standard - Future Proposals
On 10 July 2016 at 22:14, Francisco Lopes
<francisco.m...@oblita.com> wrote:
> Many thanks for that reference Ville. I see there was invitation for a
> paper, but
> no more information about it going forward, is there anything going forward
> already?
>
> I think as demonstrated, with the current and future additions to the
> standard,
> more usecases are showing up in favor of such feature.


There hasn't been recent work on it, none after that invitation to
write a paper, as far as I'm aware of.

je...@unbuggy.com

unread,
Jul 10, 2016, 4:10:04 PM7/10/16
to ISO C++ Standard - Future Proposals
_ is already used as a placeholder in the MPL. It's also sometimes used as a local macro name. You have a neat idea, but _ seems pretty well spoken for. It's also unclear that this proposal would solve a real pain point, or whether it's convenience would be outweighed by (arguably) less readable code.

I would find the feature more useful if it offered slightly less functionality; in particular, I'd like a guarantee that no operation at all can be performed on such variables except the automatic destruction at end of scope.

To these ends, would it make sense to dispense with the variable name altogether, making the objects truly anonymous?

auto = std::lock_guard<std::mutex>(mtx1);
auto = std::lock_guard<std::mutex>(mtx2);

D. B.

unread,
Jul 10, 2016, 4:20:34 PM7/10/16
to std-pr...@isocpp.org
Can we be sure no one will ever want to specify a different type at LHS in order to force a conversion operator from RHS? I know use-cases for this are limited, but are they that limited?

 

D. B.

unread,
Jul 10, 2016, 4:21:40 PM7/10/16
to std-pr...@isocpp.org
Course, maybe i'm just being overly literal, and you meant that "auto" could be any type, in which case, carry on

Francisco Lopes

unread,
Jul 10, 2016, 4:30:00 PM7/10/16
to ISO C++ Standard - Future Proposals
Agree with D.B., I'd not remove this from the original idea. Not allowing referencing _ once it's
declared multiple times in the same scope (a case that would exist solely after the feature getting in)
seems acceptable tough. It's Tony V E original proposition in the previous thread.

Francisco Lopes

unread,
Jul 10, 2016, 4:33:36 PM7/10/16
to ISO C++ Standard - Future Proposals
By the way, fyi, the discussion referred by Ville tells about using __ instead of _

Francisco Lopes

unread,
Jul 10, 2016, 5:17:21 PM7/10/16
to ISO C++ Standard - Future Proposals
Related: I just noticed that it seems compiler writers have to special-case treatment of
std guards to not give unused variable warnings?

#include <mutex>

#include <iostream>

using namespace std;

mutex m;

int main() {
    lock_guard<mutex> a(m);
    int b{0};
}

g++ -std=c++14 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'int main()':
main.cpp:10:9: warning: unused variable 'b' [-Wunused-variable]
     int b(0);

So, the unused variable analysis have to care about not warning on special cases
where non-usage is the norm.

Nevin Liber

unread,
Jul 10, 2016, 5:26:25 PM7/10/16
to std-pr...@isocpp.org
On 10 July 2016 at 16:17, Francisco Lopes <francisco.m...@oblita.com> wrote:
Related: I just noticed that it seems compiler writers have to special-case treatment of
std guards to not give unused variable warnings?

Far more likely that they don't warn on types that have non-trivial destructors.

--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com>  +1-847-691-1404

Nevin Liber

unread,
Jul 10, 2016, 5:33:39 PM7/10/16
to std-pr...@isocpp.org
Can we be sure?  Of course not.

If the user wishes to do this, they should be able to either cast the result or just name a variable.  It need not cover every possible weird use case.

Nevin Liber

unread,
Jul 10, 2016, 5:46:59 PM7/10/16
to std-pr...@isocpp.org
On 10 July 2016 at 15:10, <je...@unbuggy.com> wrote:
_ is already used as a placeholder in the MPL. It's also sometimes used as a local macro name.  You have a neat idea, but _ seems pretty well spoken for.  It's also unclear that this proposal would solve a real pain point, or whether it's convenience would be outweighed by (arguably) less readable code.

I would find the feature more useful if it offered slightly less functionality; in particular, I'd like a guarantee that no operation at all can be performed on such variables except the automatic destruction at end of scope.

This is, of course the problem.  You are looking to change functionality which has been there since C90 (or even longer).  This would break working code and introduce an incompatibility with C.  You could possibly mitigate the latter with a complicated rule (for instance, it only has the desired semantics for types with non-trivial destructors), but if you are stealing a name, you cannot help but break the former.

__ is different than _ in that it is reserved for implementations, so theoretically the breakage wouldn't be as bad.

IMO, finding a way to express this w/o using an identifier is a better approach (although then comes the debate about the feature being worth the cost of new syntax).

Ville Voutilainen

unread,
Jul 10, 2016, 5:51:03 PM7/10/16
to ISO C++ Standard - Future Proposals
On 11 July 2016 at 00:46, Nevin Liber <ne...@eviloverlord.com> wrote:
> IMO, finding a way to express this w/o using an identifier is a better
> approach (although then comes the debate about the feature being worth the
> cost of new syntax).


Also consider an idea like
Foobar = f();
vs. the syntax that already has a meaning, aka
Foobar() = f();
and the unfortunate subtlety of that difference.

Francisco Lopes

unread,
Jul 10, 2016, 5:57:20 PM7/10/16
to ISO C++ Standard - Future Proposals


Em domingo, 10 de julho de 2016 18:46:59 UTC-3, Nevin ":-)" Liber escreveu:
On 10 July 2016 at 15:10, <je...@unbuggy.com> wrote:
_ is already used as a placeholder in the MPL. It's also sometimes used as a local macro name.  You have a neat idea, but _ seems pretty well spoken for.  It's also unclear that this proposal would solve a real pain point, or whether it's convenience would be outweighed by (arguably) less readable code.

I would find the feature more useful if it offered slightly less functionality; in particular, I'd like a guarantee that no operation at all can be performed on such variables except the automatic destruction at end of scope.

This is, of course the problem.  You are looking to change functionality which has been there since C90 (or even longer).  This would break working code and introduce an incompatibility with C.  You could possibly mitigate the latter with a complicated rule (for instance, it only has the desired semantics for types with non-trivial destructors), but if you are stealing a name, you cannot help but break the former.

A far as I can see, both my proposal at the top, as well as Tony suggestion of disallowing being able to refer
to _ when multiple exist declarations exist in the same scope, are backwards compatible with what's allowed
today right? Counter example?

Also, you're correct about the compiler not giving non-used variable warnings for objects with non-trivial destructors.
I wonder whether the application of that is beneficial as such general rule or not. Non-trivial destructor are quite
an implicit use of variable.

Francisco Lopes

unread,
Jul 10, 2016, 6:18:27 PM7/10/16
to ISO C++ Standard - Future Proposals
Then, I'm just *really* surprised noticing this after this many years that
a simple "unused" std::string doesn't give a warning because of that
non-trivial destructor rule.

For me this is not a feature, it's sad!

I imagine a newcomer asking an instructor: "hey why int i gives a unused warning but string s not?"

Zhihao Yuan

unread,
Jul 10, 2016, 6:25:48 PM7/10/16
to std-pr...@isocpp.org
My suggestion has always been a simple

with (auto lk = unique_lock(lk)) {
}

which is already available as `if (auto ...; true)`,
and

with (lock_guard(lk)) {
}

whose the wording for introducing a unique name
has already presented in the structured binding
proposal.

--
Zhihao Yuan, ID lichray
The best way to predict the future is to invent it.
___________________________________________________
4BSD -- http://blog.miator.net/

Nicol Bolas

unread,
Jul 10, 2016, 7:44:03 PM7/10/16
to ISO C++ Standard - Future Proposals
Wait a minute. Let's think about what we just added to C++: structured binding:

auto [a, b] = ...;

Now, the way structured binding works is that it takes the expression and stores it in a hidden variable. It then gets references to the members, either directly from public members or with a particular interface. That's how the concept is semantically defined:

auto &&temp = make_pair(3, 4.5f);
auto &a = temp.first;
auto &b = temp.second;

So... what happens if we do this:

auto [] = ...;

If we allowed this to work for any type, then what we'd be saying is that the expression would be stored in... a hidden variable. But since the structured binding list is empty, no references would be extracted from it. So all we'd have is what we want: an unnamed, unnamable variable that will be destroyed when scope ends.

So we'd have code like this:

auto[] = scope_exit(...);

I admit that this isn't great syntax. It looks too much like structured binding. But I think it's better than trying to define that a certain identifier name would have a new meaning.

Francisco Lopes

unread,
Jul 10, 2016, 7:59:33 PM7/10/16
to ISO C++ Standard - Future Proposals
That's interesting Nicol, but what about the other cases? For structured binding itself
for example, how would I let bindings unnamed? I think this is one of the more compelling
usecases, structured binding feels a bit lacking without that mechanism.

Francisco Lopes

unread,
Jul 10, 2016, 8:02:48 PM7/10/16
to ISO C++ Standard - Future Proposals
I mean, not all bindings.

Zhihao Yuan

unread,
Jul 10, 2016, 8:49:07 PM7/10/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 6:44 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Wait a minute. Let's think about what we just added to C++: structured
> binding:
>
> auto [a, b] = ...;

Currently this syntax is outlawed, but I expect that
in the future we extend the identifier-list inside
structured binding to support pack expansion:

auto [a...] = expr;

where an empty pack naturally decompose an
empty product type. Sooner or later you will
find that smoothly and consistently handle the
zero cases will reward you back.

Nicol Bolas

unread,
Jul 10, 2016, 9:11:16 PM7/10/16
to ISO C++ Standard - Future Proposals
On Sunday, July 10, 2016 at 7:59:33 PM UTC-4, Francisco Lopes wrote:
That's interesting Nicol, but what about the other cases? For structured binding itself
for example, how would I let bindings unnamed?

Remember the goal: you want an object to be unnamed, because you want to use its construction and destruction only. The variables created by structured binding are not objects; they're references. Their destructors are irrelevant, so making them unnamed is equally irrelevant to this particular goal.

Don't try to solve every problem at once.

Nicol Bolas

unread,
Jul 10, 2016, 9:11:57 PM7/10/16
to ISO C++ Standard - Future Proposals


On Sunday, July 10, 2016 at 8:49:07 PM UTC-4, Zhihao Yuan wrote:
On Sun, Jul 10, 2016 at 6:44 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Wait a minute. Let's think about what we just added to C++: structured
> binding:
>
> auto [a, b] = ...;

Currently this syntax is outlawed,

I didn't mean `...` as in parameter pack. I meant `...` as in `something`.

Francisco Lopes

unread,
Jul 10, 2016, 9:53:11 PM7/10/16
to ISO C++ Standard - Future Proposals
 
That may look like the original goal in the previous thread, but to tell the truth it's not my goal. The rationale
here is for unnamed variables. It's just about to cover the intention of not providing names for things
that doesn't need them, as frequently happen (and will happen) in the cases presented.


Don't try to solve every problem at once.
 
Why not? It's a simple solution that covers the relevant problem: having a placeholder. It ends up
solving all in an understandable manner, in a uniform way. I ask why solve it in a case by case form?
or solving one special case while leaving the others for the future or plain unsolved, when in truth,
they all refer to the same core subject.


Francisco Lopes

unread,
Jul 10, 2016, 10:08:39 PM7/10/16
to ISO C++ Standard - Future Proposals
Besides _ or __ I'm thinking of other possibilities...

 @: I know of its presence solely in mangled names but I suspect it won't be an issue.

I dunno, maybe the range of special characters may be of some use here too.

Francisco Lopes

unread,
Jul 10, 2016, 10:12:32 PM7/10/16
to ISO C++ Standard - Future Proposals


Em domingo, 10 de julho de 2016 23:08:39 UTC-3, Francisco Lopes escreveu:
Besides _ or __ I'm thinking of other possibilities...

 @: I know of its presence solely in mangled names but I suspect it won't be an issue.

I dunno, maybe the range of special characters may be of some use here too.

If adopting such alternative characters, it would be placeholder only, without referentiability.

Francisco Lopes

unread,
Jul 10, 2016, 10:23:01 PM7/10/16
to ISO C++ Standard - Future Proposals


Em domingo, 10 de julho de 2016 23:12:32 UTC-3, Francisco Lopes escreveu:


Em domingo, 10 de julho de 2016 23:08:39 UTC-3, Francisco Lopes escreveu:
Besides _ or __ I'm thinking of other possibilities...

 @: I know of its presence solely in mangled names but I suspect it won't be an issue.

I dunno, maybe the range of special characters may be of some use here too.

If adopting such alternative characters, it would be placeholder only, without referentiability.

My preferred choices are _, @ or ?

Ricardo Fabiano de Andrade

unread,
Jul 10, 2016, 11:07:07 PM7/10/16
to std-pr...@isocpp.org
I've been following this with great interest but I disagree with using _, __, @, etc.

If the goal of a future proposal is having unnamed variables IMHO they should not use any character or sequence of characters to be... well ... named.

The examples where a member function needs to be called on a unnamed variable is just something that could be done by another function which the return is assigned to a unnamed variable.
Or other cases, another RAII class could wrap this and calling whatever member functions on its constructor/destructor.

Nicol's suggestion:
auto[] = foo();
It seems to me a better direction.

For the cases where named and unnamed variables are needed, may we just skip declaring a name?
auto [a,,c] = foo();
Or would that be too error prone?

A few other thoughts:
- Should unnamed variables should also be allowed whenever a structured binding is possible?
  I'm thinking unnamed statics/globals here.

- It was also mentioned that structured binding creates references... but which kind of references are they?
  const& and && are known to extend the lifetime of the assigned object until the end of the scope.

- Regarding structured binding type deduction and conversions: there was some discussion around allowing specifying the types of individual variables.
  How that would apply to unnamed variables?
  Wrap conversions in other functions or classes (as suggested above for when member function calls are needed)?
  Or just don't for now...
  If structured binding ever gets this ability in the future, then types for unnamed variables could be specified: auto[int a, int, int b] = foo();

- Is there a use case for unnamed class data members?
  Maybe for some crazy future use of parameter pack expansion?
  Then auto[] would not work.

- I'm trying to find similarities with other situations where an entity can be unnamed as a case for consistency ...
  anonymous unions/structs or namespaces, type of a lambda...
  Well, maybe those are different beasts.


--
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/69941075-9183-403b-86ac-3e37b7ddfae1%40isocpp.org.

Nicol Bolas

unread,
Jul 10, 2016, 11:38:32 PM7/10/16
to ISO C++ Standard - Future Proposals
On Sunday, July 10, 2016 at 11:07:07 PM UTC-4, Ricardo Andrade wrote:
I've been following this with great interest but I disagree with using _, __, @, etc.

If the goal of a future proposal is having unnamed variables IMHO they should not use any character or sequence of characters to be... well ... named.

@ is not even in the C++ basic character set. So it cannot be a valid identifier.

That being said, I dislike using @ for 2 reasons:

1: It requires adding `@` to the basic character set.
2: After having gone through the effort to add a character to the basic character set, we would then use up all of the possible syntactic potential of the character, just to get unnamed identifiers. Better to preserve the possibilities for `@` for something more worthwhile.

Francisco Lopes

unread,
Jul 10, 2016, 11:45:33 PM7/10/16
to ISO C++ Standard - Future Proposals
Hi Ricardo, maybe the topic name is improper. First, I'm advocating that if any special character
is to be used besides _ and __, which are already usable as indentifiers, then it would
not be possible to explicitly call member functions on them, they would simpler serve the purpose
of a placeholder name at declaration.

I like this idea of a placeholder variable name better than the current propositions. It's not the
same as truly anonymous for which you don't even give it a name at all, but it's better IMO.
I see no reason for tackling it solely by extending syntax of structure binding and missing the
oportunity for all the possible remaining usecases where the presence of a placeholder name would
solve it. A placeholder doesn't even need to tweak structure binding specification at all, it would be
solved as a consequence of a more general solution about variable naming.

Nicol Bolas

unread,
Jul 10, 2016, 11:47:14 PM7/10/16
to ISO C++ Standard - Future Proposals
On Sunday, July 10, 2016 at 9:53:11 PM UTC-4, Francisco Lopes wrote:

Em domingo, 10 de julho de 2016 22:11:16 UTC-3, Nicol Bolas escreveu:
On Sunday, July 10, 2016 at 7:59:33 PM UTC-4, Francisco Lopes wrote:
That's interesting Nicol, but what about the other cases? For structured binding itself
for example, how would I let bindings unnamed?

Remember the goal: you want an object to be unnamed, because you want to use its construction and destruction only. The variables created by structured binding are not objects; they're references. Their destructors are irrelevant, so making them unnamed is equally irrelevant to this particular goal.
 
That may look like the original goal in the previous thread, but to tell the truth it's not my goal. The rationale
here is for unnamed variables. It's just about to cover the intention of not providing names for things
that doesn't need them, as frequently happen (and will happen) in the cases presented.

Don't try to solve every problem at once.
 
Why not? It's a simple solution that covers the relevant problem: having a placeholder. It ends up
solving all in an understandable manner, in a uniform way.

But it is not a "simple solution". Indeed, I would go so far as to say that any placeholder which is currently a valid identifier is not a solution at all.

Breaking people's perfectly valid code should not be considered a solution to a problem. Not without really good reason. And let's face facts: unnamed variables are not that important.

Also, last time we tried to get something "uniform", we got Uniform Initialization. Which very much is not.

I ask why solve it in a case by case form?

Because it works. Not only does it work, it makes sense. That's one of the nice things about `auto[]`: based solely on the rules of structured binding, it does exactly what you want.

Indeed, as I think about it, if we ever wanted structured binding to be able to not capture all of the elements, we wouldn't want it to use placeholders. We would probably want `auto [x]` to bind to the first value of any tuple-like type. If that type has 30 variables in it, I don't care; I just want the first one. I shouldn't have to do `auto [x, @, @, @]` or even `auto [x, ...]` or whatever. I said that I wanted the first member, so give it to me.

Given that, `auto []` would bind to none of the values. Therefore, it would either be a compile error or it would work on anything, providing a hidden object that would be destroyed at the end of scope.

So really, I don't see this as a "case-by-case form". It's really the right way to go for both problems ;)

Zhihao Yuan

unread,
Jul 10, 2016, 11:53:34 PM7/10/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 10:47 PM, Nicol Bolas <jmck...@gmail.com> wrote:
> Indeed, I would go so far as to say that any placeholder which is currently
> a valid identifier is not a solution at all.

How about

register lock_guard(lk);

Not a currently valid identifier, correct English :)

Ricardo Fabiano de Andrade

unread,
Jul 10, 2016, 11:59:10 PM7/10/16
to std-pr...@isocpp.org
If I'm following Francisco's line of thought that would not work for:
auto [a, register, c] = foo();

Or for:
[a, register = b, c]() { ... }

The suggestion is for something that can be used during the variable declaration which make it valid but inaccessible since it does not have a name.


--
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.

Nicol Bolas

unread,
Jul 11, 2016, 12:09:45 AM7/11/16
to ISO C++ Standard - Future Proposals
On Sunday, July 10, 2016 at 11:59:10 PM UTC-4, Ricardo Andrade wrote:
If I'm following Francisco's line of thought that would not work for:
auto [a, register, c] = foo();

Why wouldn't that work? `register` is a valid keyword but currently has no meaning. Therefore, its usage in structured binding has no meaning.

Which means we can make it work however we want.

Ricardo Fabiano de Andrade

unread,
Jul 11, 2016, 12:12:43 AM7/11/16
to std-pr...@isocpp.org
Well, if that's the case, the idea is not half bad. :)
"register"ing a variable sounds even reasonable.

--
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.

Francisco Lopes

unread,
Jul 11, 2016, 12:13:02 AM7/11/16
to ISO C++ Standard - Future Proposals


Em segunda-feira, 11 de julho de 2016 00:47:14 UTC-3, Nicol Bolas escreveu:
On Sunday, July 10, 2016 at 9:53:11 PM UTC-4, Francisco Lopes wrote:

Em domingo, 10 de julho de 2016 22:11:16 UTC-3, Nicol Bolas escreveu:
On Sunday, July 10, 2016 at 7:59:33 PM UTC-4, Francisco Lopes wrote:
That's interesting Nicol, but what about the other cases? For structured binding itself
for example, how would I let bindings unnamed?

Remember the goal: you want an object to be unnamed, because you want to use its construction and destruction only. The variables created by structured binding are not objects; they're references. Their destructors are irrelevant, so making them unnamed is equally irrelevant to this particular goal.
 
That may look like the original goal in the previous thread, but to tell the truth it's not my goal. The rationale
here is for unnamed variables. It's just about to cover the intention of not providing names for things
that doesn't need them, as frequently happen (and will happen) in the cases presented.

Don't try to solve every problem at once.
 
Why not? It's a simple solution that covers the relevant problem: having a placeholder. It ends up
solving all in an understandable manner, in a uniform way.

But it is not a "simple solution". Indeed, I would go so far as to say that any placeholder which is currently a valid identifier is not a solution at all.

Restating that it's not just about reusing already valid identifiers. 
 

Breaking people's perfectly valid code should not be considered a solution to a problem. Not without really good reason. And let's face facts: unnamed variables are not that important.

I've asked before about a sample where the proposals I've endorsed would break people's code, do you have one (seriously)?

For the case where _ can be overridden, there's no codebase that can compile with variables of equal name are declared, same
applies for the solution where _ can't be referenced if declared more than once in the same scope.
 

Also, last time we tried to get something "uniform", we got Uniform Initialization. Which very much is not.

I ask why solve it in a case by case form?

Because it works. Not only does it work, it makes sense. That's one of the nice things about `auto[]`: based solely on the rules of structured binding, it does exactly what you want.

Indeed, as I think about it, if we ever wanted structured binding to be able to not capture all of the elements, we wouldn't want it to use placeholders. We would probably want `auto [x]` to bind to the first value of any tuple-like type. If that type has 30 variables in it, I don't care; I just want the first one. I shouldn't have to do `auto [x, @, @, @]` or even `auto [x, ...]` or whatever. I said that I wanted the first member, so give it to me.

Given that, `auto []` would bind to none of the values. Therefore, it would either be a compile error or it would work on anything, providing a hidden object that would be destroyed at the end of scope.

You may like that, I don't. You are focusing on a special solution for the
sake of bad practice on multiple return. I'm looking for this solved:

auto [x, _, y] = foo()
auto [_, y, _] = bar()
auto [x, _] = baz()

Etc, which your solution where order matters, doesn't cover (besides not covering the other case).
The time I get a tuple of 30 as a return, I'd be looking for a refactor not support of the language for
pattern handling of that.
 

So really, I don't see this as a "case-by-case form". It's really the right way to go for both problems ;)


Which both? You mean the correct way is to patch the language around the same subject, but with
particular solutions?

Ricardo Fabiano de Andrade

unread,
Jul 11, 2016, 12:19:32 AM7/11/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 10:45 PM, Francisco Lopes <francisco.m...@oblita.com> wrote:
Hi Ricardo, maybe the topic name is improper. First, I'm advocating that if any special character
is to be used besides _ and __, which are already usable as indentifiers, then it would
not be possible to explicitly call member functions on them, they would simpler serve the purpose
of a placeholder name at declaration.


Now I think I understand the reach of your suggestion. Any variable, anywhere, could be unnamed.
As long as it becomes inaccessible after being "declared" I can see some benefit.
 
I like this idea of a placeholder variable name better than the current propositions. It's not the
same as truly anonymous for which you don't even give it a name at all, but it's better IMO.

I can also see some problems.
- I'm not quite sure if I want unnamed variables everywhere.
  At the local scope, it seems pretty straightforward. Global, namespace, static and class scopes I'm not so sure.
  In the other hand, I'm also against artificial constraints to prevent such uses if this suggestion ever becomes a proposal.
- I was about to say that finding such placeholder "name" sounded difficult. But it seems we got a candidate "register".
 
I see no reason for tackling it solely by extending syntax of structure binding and missing the
oportunity for all the possible remaining usecases where the presence of a placeholder name would
solve it. A placeholder doesn't even need to tweak structure binding specification at all, it would be
solved as a consequence of a more general solution about variable naming.


Sounds reasonable. :)
 

Zhihao Yuan

unread,
Jul 11, 2016, 12:20:20 AM7/11/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 10:59 PM, Ricardo Fabiano de Andrade
<ricardofabi...@gmail.com> wrote:
> If I'm following Francisco's line of thought that would not work for:
> auto [a, register, c] = foo();

I want to solve the problem of RAII, not structured
binding. Feel free to extend structured binding,
but I don't find making them work in the same
way very fascinating.

Tony V E

unread,
Jul 11, 2016, 12:28:25 AM7/11/16
to Zhihao Yuan
We could solve RAII with register, and leave it at that. 

But I solution for structured binding would also be nice. 
And if/when we get pattern matching, we will really need something short that means 'match any'. auto does that for types, but we need something for values. 

We could solve each of these independently, but if #3 also solves #2 and #1 *coherently*, then I'd rather have a single solution.

If a single solution is incoherent, then we shouldn't push it. But we need to explore it. 

I'm not sure solving any one problem is worth it on its own, but if you can solve all three (and more), then you have bang for the buck. 
 

Sent from my BlackBerry portable Babbage Device
  Original Message  
From: Zhihao Yuan
Sent: Monday, July 11, 2016 12:20 AM
To: std-pr...@isocpp.org
Reply To: std-pr...@isocpp.org
Subject: Re: [std-proposals] Re: Anonymous variables (moved "deferred destruction" topic)
--
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/CAGsORuD5GZataPFFfzKTxO7zMgLfkcTFS6uGq6GputasiwF10g%40mail.gmail.com.

Francisco Lopes

unread,
Jul 11, 2016, 12:33:11 AM7/11/16
to ISO C++ Standard - Future Proposals
About "which both", nevermind. I got what you suggests covers both guards, scope_exit
and structure binding, although for the last it doesn't look much useful as a solution.

Francisco Lopes

unread,
Jul 11, 2016, 12:40:17 AM7/11/16
to ISO C++ Standard - Future Proposals
ah, correction, as far as I can see it doesn't work very well for normal declarations
like with guards. Also, I have no idea whether structure binding should support things
that I have no idea can be destructured or not. So it looks pretty much trying to
sneak from recently added structure biding to other areas it's was not thought for.

Zhihao Yuan

unread,
Jul 11, 2016, 12:40:47 AM7/11/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 11:28 PM, Tony V E <tvan...@gmail.com> wrote:
>
> We could solve each of these independently, but if #3 also solves #2 and #1 *coherently*, then I'd rather have a single solution.
>
> If a single solution is incoherent, then we shouldn't push it. But we need to explore it.

Let's say we use the keyword `register` as the placeholder
for the solution this thread is looking for, RAII will be written
as

auto register = lock_guard(lk);

Lengthy. And structured binding will be

auto [a, register] = ...;

I want to "ignore", not *not* to ignore.

This way damages both use cases.

>
> I'm not sure solving any one problem is worth it on its own, but if you can solve all three (and more), then you have bang for the buck.

Instead, if we have

register lock_guard(lk);

and

auto [a, std::ignore] = expr;

Both intentions seem to be expressed very well.

The point I'm making here is that, for the RAII case,
what you want is to emphasis the existence of the
unnamed variable, while in structured binding/pattern
matching, what you want is to eliminate the presence
of the unnamed variable. They are not necessarily
to be using the same solution.

Francisco Lopes

unread,
Jul 11, 2016, 12:55:38 AM7/11/16
to ISO C++ Standard - Future Proposals
Hi Zhihao. Of course it doesn't necessarily need to be any way.
I get your point, but the solutions you give to cover that point are
not much pretty.


Em segunda-feira, 11 de julho de 2016 01:40:47 UTC-3, Zhihao Yuan escreveu:
On Sun, Jul 10, 2016 at 11:28 PM, Tony V E <tvan...@gmail.com> wrote:
>
> We could solve each of these independently, but if #3 also solves #2 and #1 *coherently*, then I'd rather have a single solution.
>
> If a single solution is incoherent, then we shouldn't push it. But we need to explore it.

Let's say we use the keyword `register` as the placeholder
for the solution this thread is looking for, RAII will be written
as

  auto register = lock_guard(lk);

Lengthy.

register is not meaningful, it doesn't bring the sense of a placeholder, I think this is bad.
 
And structured binding will be

  auto [a, register] = ...;

I want to "ignore", not *not* to ignore.

Indeed, me too! Same for the previous.

This way damages both use cases.

>
> I'm not sure solving any one problem is worth it on its own, but if you can solve all three (and more), then you have bang for the buck.

Instead, if we have

  register lock_guard(lk);

OK so, register is still not meaningful about anything as a name, and what is it doing
at the variable type? I have to bend my mind to understand that's an anonymous declaration
of a lock_guard.

and

  auto [a, std::ignore] = expr;

Have you checked in a previous Nicol email how structure binding should expand behind
the scenes. Having a placeholder variable name fits well with that, now std::ignore doesn't,
I can't imagine what the implementation of that should be like. I agree the intention is
present though, in this case.

Zhihao Yuan

unread,
Jul 11, 2016, 1:08:36 AM7/11/16
to std-pr...@isocpp.org
On Sun, Jul 10, 2016 at 11:55 PM, Francisco Lopes
<francisco.m...@oblita.com> wrote:
>> Instead, if we have
>>
>> register lock_guard(lk);
>
>
> OK so, register is still not meaningful about anything as a name, and what
> is it doing
> at the variable type? I have to bend my mind to understand that's an
> anonymous declaration
> of a lock_guard.
>

It's even easier to understand than "unnamed variable".
Given

lock_guard(lk);

as an expression statement -- a _discarded-value
expression_ alone followed by a semicolon,

register lock_guard(lk);

statement will be a statement that keep the value to-be-
discarded. Or you can say, "registered".

Francisco Lopes

unread,
Jul 11, 2016, 1:13:03 AM7/11/16
to ISO C++ Standard - Future Proposals
Hah, ok, now I get it. In that sense it seems fine.

Francisco Lopes

unread,
Jul 11, 2016, 1:22:56 AM7/11/16
to ISO C++ Standard - Future Proposals
Now I agree with being an acceptable solution for the RAII problem, it covers both
scope_exit and guards. Sadly it doesn't touch binding as you already said.

The problem is that the time we get a mechanist to let variables unnamed (like
with got for types like Tony said), and I hope so this happens. Then we will end
up with two valid solutions for the RAII problem I guess. It would not happen only
if placeholders are put at work in specific places solely, which personally I'd not
like.

Zhihao Yuan

unread,
Jul 11, 2016, 2:02:27 AM7/11/16
to std-pr...@isocpp.org
On Mon, Jul 11, 2016 at 12:22 AM, Francisco Lopes
<francisco.m...@oblita.com> wrote:
> The problem is that the time we get a mechanist to let variables unnamed
> (like
> with got for types like Tony said), and I hope so this happens. Then we will
> end
> up with two valid solutions for the RAII problem I guess. It would not
> happen only
> if placeholders are put at work in specific places solely, which personally
> I'd not
> like.

Structured binding is a prototype for pattern matching,
IMHO it's acceptable for having some features not
usable outside [], as acceptable as having features
usable from outside but not inside, which is the status
quo.

To this specific "ignore" functionality, restricting it
within structured binding gives us a long list of
placeholder candidates:

.. // two dots
<>
- // minus, dash
~
:)

, while making it usable in other places is troublesome
in some cases:

int <placeholder> = get_raii_file_descriptor();

That RAII fd is implicitly convertible to int, so we
destroy the object and return an int? Or we restrict
the type to be `auto`? Oh wait, actually I need
`auto&&`! Welcome home, that is exactly how
structured binding handles the "capturing object",
and by doing this we subset the language in a
much larger scope...

Thiago Macieira

unread,
Jul 11, 2016, 2:44:00 AM7/11/16
to std-pr...@isocpp.org
On domingo, 10 de julho de 2016 15:18:26 PDT Francisco Lopes wrote:
> I imagine a newcomer asking an instructor: "hey why int i gives a unused
> warning but string s not?"

Answer: "because int is trivial, std::string isn't"

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

Thiago Macieira

unread,
Jul 11, 2016, 2:45:27 AM7/11/16
to std-pr...@isocpp.org
On domingo, 10 de julho de 2016 19:08:38 PDT Francisco Lopes wrote:
> @: I know of its presence solely in mangled names but I suspect it won't
> be an issue.

It's not part of the basic character set.

Tony V E

unread,
Jul 11, 2016, 7:20:02 AM7/11/16
to Zhihao Yuan
Hmmm
Maybe we should reserve _ as unusable in structured binding for now?

Sent from my BlackBerry portable Babbage Device
  Original Message  
From: Zhihao Yuan
Sent: Monday, July 11, 2016 2:02 AM
To: std-pr...@isocpp.org
Reply To: std-pr...@isocpp.org
Subject: Re: [std-proposals] Re: Anonymous variables (moved "deferred destruction" topic)

--
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/CAGsORuBtbE1doTfQAXXTtV%3DTLE%2Br%3DCyRVN-t_dLzSbw%3DDL_epQ%40mail.gmail.com.

Francisco Lopes

unread,
Jul 11, 2016, 10:08:34 AM7/11/16
to ISO C++ Standard - Future Proposals


Em segunda-feira, 11 de julho de 2016 08:20:02 UTC-3, Tony V E escreveu:
Hmmm
Maybe we should reserve _ as unusable in structured binding for now?

I consider it a wise move.

Francisco Lopes

unread,
Jul 11, 2016, 10:14:43 AM7/11/16
to ISO C++ Standard - Future Proposals


Em segunda-feira, 11 de julho de 2016 11:08:34 UTC-3, Francisco Lopes escreveu:


Em segunda-feira, 11 de julho de 2016 08:20:02 UTC-3, Tony V E escreveu:
Hmmm
Maybe we should reserve _ as unusable in structured binding for now?

I consider it a wise move.

If structured binding alone supported a placeholder already, it could be done in
a way that would support both auto [x, _, y] = ..., was well as auto [] = ...

Daniel Frey

unread,
Jul 11, 2016, 11:26:48 AM7/11/16