std::lock_guard<std::mutex> _(mtx);
auto _ = finally([]{ std::cout << "scope exit\n"; }); // 'finally' runs a function at scope exit
void foo(int _);
struct _ { ... } my_single_object;
--
---
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 http://groups.google.com/a/isocpp.org/group/std-proposals/.
Idea: Give a single underscore "_" a special meaning in contexts where an identifier is expected.
Am Freitag, 7. März 2014 17:03:44 UTC+1 schrieb Nevin ":-)" Liber:
On 7 March 2014 02:07, Stack Machine <stackm...@hotmail.com> wrote:
Idea: Give a single underscore "_" a special meaning in contexts where an identifier is expected.That would be a breaking change, which significantly reduces the chance that the committee will ever approve it.
Yes, but how relevant is it in practise? I do not see any good reason, why you would want to use _ as an identifier.
I haven't used gettext so far, so I am going to take a look at it. But I think even then, it's worth the trade-off.
--
--- You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposals+unsubscribe@isocpp.org.
std::lock_guard<std::mutex> = mtx;
auto = finally([]{ std::cout << "scope exit\n"; }); // 'finally' runs a function at scope exit
void foo(int);
struct { ... } my_single_object;
Idea: Give a single underscore "_" a special meaning in contexts where an identifier is expected. It means that the thing being defined is unused.
Examples:
std::lock_guard<std::mutex> _(mtx);
auto _ = finally([]{ std::cout << "scope exit\n"; }); // 'finally' runs a function at scope exit
void foo(int _);
struct _ { ... } my_single_object;
On 7 March 2014 02:07, Stack Machine <stackm...@hotmail.com> wrote:Idea: Give a single underscore "_" a special meaning in contexts where an identifier is expected.That would be a breaking change, which significantly reduces the chance that the committee will ever approve it.
Idea: Give a single underscore "_" a special meaning in contexts where an identifier is expected. It means that the thing being defined is unused.
Examples:
etc. etc.std::lock_guard<std::mutex> _(mtx);
auto _ = finally([]{ std::cout << "scope exit\n"; }); // 'finally' runs a function at scope exit
void foo(int _);
struct _ { ... } my_single_object;
This feature has been used extensively in functional languages. It solves the problem of unused variables nicely while being very explicit at the same time.
You missed the point.
If I'm writing a header, I don't know whether my header will be included after
the header that #defines _. If it is included after, then I can't use _ since
it will expand to gettext, which is not a special identifier.
Therefore, I may never use this feature in headers. Ever.
But usually I also take care not to name my variables after identifiers that
are usually #defined to something. That's why you never call your variables
O_RDONLY, interface, sun, linux, s6_addr, sa_handler, m_volume, or _.
I think there's a valid use-case in this thread for anonymous variables, just
like we can have anonymous parameters and anonymous fields in a bitfield. I'm
simply arguing against using _ as a special identifier.
...then what does __attribute__((warn_unused_result)) do? As I understood it is *exactly* dealing with cases such as the above.
Although it doesn't address the case:
scope_guard{...};
...though I would be somewhat surprised if that isn't already warned about.
That said...1. explicit operator void() discard operator prevents discarding the
return value -- non-breaking core language change, with application
to expression templates.
...this sounds like it would be an interesting addition. (I take it this would make failure to assign such a class to a named identifier an error?)
Alternative solutions, requiring core language changes, may be explored. Here are two.
2.1.1. Discarded value operator
As a purely diagnostic measure, the guard class could be forbidden from forming a discarded value expression. Another case where trapping discarded values is useful is a matrix expression template involving multiple assignment operations. Currently, an expression template must decay at each assignment operation, ignoring some loop interleavings. The relevance here is that such a feature would not be dedicated to guard safety.
The natural discarded value operator is operator void(). An expression-statement with type T could be considered as an implicit conversion from T to void, therefore a guard class would only need to declare explicit operator void() {} to give the example an illegal implicit conversion. Explicitly casting a guard object to void would still be legal.
2.1.2. Restriction of class value category
The class could be forbidden from forming a prvalue expression. This would forbid the guard ever being an anonymous, discarded object. Function return values are always of category prvalue though, so the best middle ground is to also permit a lifetime-extended temporary.
The restriction could be expressed by a class-head decorator such as &. The corresponding && decorator would conversely express that instances cannot be named (or lifetime-extended), such as expression template specializations. Inheritance of this decorator is a difficult question. One simple solution is to make them class-virt-specifiers implying final, thus prohibiting derivation.
This rather elegantly removes the danger, but it does not improve convenience. The ideal solution would simply fix the bare function call expression to be correct. Such a & specifier may be sufficiently expressive to allow the language to surmise that a discarded prvalue, rather than being ill-formed, should be interpreted as being bound to an anonymous reference.