4 ms·
Syntax, Schmyntax... I learned too many languages over the years and can't remember every syntax from the top of my head, but does it really matter?
by OtomotO 2y ago
Syntax, Schmyntax... I learned too many languages over the years and can't remember every syntax from the top of my head, but does it really matter?
- nly 2y agoYeah it matters given how the whole argument falls on advanced aspects of the type system and templates. How can you speak with authority about a language you clearly aren't using day to day? I have never once missed the distance of an optional<T&>. The practical use of optional<> is that you know where T is going to be constructed and can reason about the memory layout. Using it as an alternative to T* has never even occurred to me. The ideal of bundling a presence flag and a pointer together (which would be the default underlying representation unless it was specialised to hold a T* internally) is gross and inefficient
- blegr 2y ago> The practical use of optional<> is that you know where T is going to be constructed and can reason about the memory layout. The practical use for me is making interfaces safer. Where I saw colleagues use pointers as optionals, end up mis-tracking what can be null and what can't, only checking it inconsistently, and triggering UB, I now have a clear distinction between optional and non-optional arguments/returns with an easy way to access the contained .value() without risk of UB. The type also tells me when I should handle the empty case and when I shouldn't. Most of the time, I want to pass/return a reference and the lack of `optional<&T>` makes it tiring. If only `std::reference_wrapper` had a shorter name, I could at least use that. But then I'd end up with `arg.value().get().attr` when `.value().attr` should be enough...
- frutiger 2y ago> Most of the time, I want to pass/return a reference Surprised to hear that you want to return a reference so frequently.
- mathstuf 2y agoThese kinds of discussions remind me that not everyone codes in the same domain where the same patterns dominate. I think everyone would do well to avoid "but I don't need it, so it seems unnecessary" kinds of arguments and instead have the imagination that others may code in different domains where different patterns dominate. Me? References get returned all the time because you want to access some state store's vector of things without copying the vector just to ask "are any of the elements X?" or adding a new method for every `std::algorithm` method for each member you might want to use it on. The benefit of `optional<T&>` over `T*` in an API is that the former communicates "you have write access to this thing which may not exist" whereas the second needs documentation for whether `nullptr` is a thing and whether the caller needs to `delete` it (or was it `delete[]` this time?).
- frutiger 2y ago> I think everyone would do well to avoid "but I don't need it, so it seems unnecessary" kinds of arguments This is an uncharitable characterisation of what I said. > References get returned all the time because you want to access some state store's vector of things without copying the vector just to ask "are any of the elements X?" This is what const references are for. Returning an optional<vector<T>&> to query if it contains an element would not be appropriate.
- blegr 2y agoIt's not really my choice, I'm working in a big codebase I didn't write. Lots of large classes containing large collections with getters and setters.
- frutiger 2y agoAh, that’s unfortunate.
- School-Cotton 2y agoHow else would you implement C++’s vector::operator[] for example? This to me is the clearest example of something that’s safe in Rust, and impossible to make safe in C++.
- tialaramex 2y ago> The ideal of bundling a presence flag and a pointer together (which would be the default underlying representation unless it was specialised to hold a T* internally) is gross and inefficient That's a defect in C++ rather than some principled objection though. Rust's Option isn't specialized, the Guaranteed Niche Optimisation kicks in exactly the same for &T as for most C-style enumerations, OwnedFd, NonZeroU8 or indeed my BalancedI8, this is one of those places where an engineer can see how to design the core language properly to deliver the same performance despite better ergonomics for everybody, not add a special hack. In practice since C++ can't do that, the likely C++ 26 std::optional<T&> will be a specialization which just has a pointer inside it. This may mean lots of awkward word smithing to require that implementation or they may just trust that all the implementers will Do The Right Thing™, as with the Niebloids. I try not to "speak with authority" about C++ because I don't think anybody has the necessary understanding to do so, including the people who wrote the ISO document, the compiler engineers, and Bjarne himself.