3 ms·
template <typename T> struct optional { // One version of value which works for everything template <class Self> constexpr auto&& value(th
by codeflo 3y ago
template <typename T>
struct optional {
// One version of value which works for everything
template <class Self>
constexpr auto&& value(this Self&& self) {
if (self.has_value()) {
return std::forward<Self>(self).m_value;
}
throw bad_optional_access();
}
The fact that I can read this and don't even find it that terrible is proof that C++ has permanently damaged my brain.
- gumby 3y agoWhy? It’s hard or impossible to even express something like this in most languages, and deducing this makes it more compact and clear.
- zabzonk 3y agoi've been using c++ since the mid 80s (cfront), and it is my favourite language, but i sometimes have bad thoughts about modern c++ syntax - if double ampersands (logic op excepted) are now with us, can triple ampersands be far behind? i wish we could maybe introduce a few new keywords. mind you, i feel much the same regarding rust syntax.
- NoOneSpecialII 3y agoTriple ampersand already came up somewhere. I don't quite remember in what context but iirc they simplify to normal lvalue refs (at least in that context).
- Arech 3y agoI think you're talking about perfect forwarding and reference collapsing rules [1, 2], introduced in C++11, but that is a bit different thing occurring only in a template instantiation context. Normally, you wouldn't see triple ampersands in sane C++ code, afaik. [1] http://thbecker.net/articles/rvalue_references/section_08.html http://thbecker.net/articles/rvalue_references/section_08.ht... [2] https://en.cppreference.com/w/cpp/language/reference https://en.cppreference.com/w/cpp/language/reference
- ziml77 3y agoOne question I have about the double ampersands when applied to types is: do they represent two different concepts depending on usage? Like I know that they indicate an rvalue reference, but they're also used for perfect forwarding. Those two concepts don't seem inherently connected to me, so the double ampersands appear to be overloaded here. Is that the case or is there some relation I'm missing?
- gumby 3y agoI think of the rvalue reference as talking about the object itself rather than how you get to it (i.e. the actual bytes on a chip someplace as opposed to its address or a copy of an object). Hence moving, perfect forwarding, etc are roughly-synonymous ways to think of managing that object, maybe just looking at the same semantics from different angles. This is just a conceptualisation, of course (rvalue definition is a little more subtle), but for me as a Lisp programmer it seems natural and intuitive. If you come from a different background or perspective I understand that it can seem weird — again, most languages are not as expressive. The low level nature that is fundamental to C++, even when you are programming at a very high level, which you now conveniently can, is a consequence of it working hard to be a zero-cost-abstraction systems programming language, leads to issues like this one, or to some odd consequences of move constructors. There are alternative points in the solution space. Compare it to go, which explicitly papers over some of these trade offs, making an opinionated choice instead, and being willing to embrace reduced expressive power (so there are some things you just can’t write in it). I don’t like go myself, but that doesn’t mean people who choose it are fools.
- magnio 3y agoYes. It normally indicates an rvalue reference, but in the context of deducing types (for example, in template instantiation or auto deduction), it can mean a forwarding reference and has a rather special meaning.[1][2] [1]: https://eli.thegreenplace.net/2014/perfect-forwarding-and-universal-references-in-c#reference-collapsing-and-special-type-deduction-for-rvalues https://eli.thegreenplace.net/2014/perfect-forwarding-and-un... [2]: https://en.cppreference.com/w/cpp/language/reference#Forwarding_references https://en.cppreference.com/w/cpp/language/reference#Forward...
- gumby 3y agoEvery keyword (unlike a symbol in std::) risks colliding with existing code, so reuse is greatly preferred. Yes, it is, to be diplomatic, highly imperfect, but working to avoid breaking existing code is one reason C++ is so successful.
- zabzonk 3y agoyeah, i know all about that. but still, i think that c++ (and c, for that matter) could do with more alphabetic keywords. and after all, the original language introduced quite a few!
- badsectoracula 3y agoWouldn't C's approach with macros help? E.g. the language defines a keyword like _Foobar which is supposed to be used via #include <foobar> that defines a "#define foobar _Foobar" macro, thus avoiding any collisions with existing code and any new code that needs to use the new keyword can opt-in and deal with any collisions (since the code will be modified anyway).
- zabzonk 3y agostroustrup's ambition for c++ was to get rid of the preprocessor (unfufilled, sadly). also, defining a name such as _Foobar does not avoid a clash with existing code - names like that are reserved in c++ and may be used by the standard library.
- dkersten 3y agoThe standard library is at least under the control of the people implementing the standard, which is much smaller breakage (ie can be fixed at the time of implementing support for the keyword) than breaking a random users code. The standard could go as far as to say what <foobar> should provide and then leave it up to the implementation what the actual non-aliased keyword actually is: maybe it’s _Foobar or maybe it’s something else, the end user won’t know because you just use foobar after including <foobar>
- 3y ago
- contravariant 3y agoPossibly, I mean I can't even figure out where the first brace closes.
- classified 3y agoStill, the code quadruplication it replaces is no less gaga.