Hacker News new | ask | show | jobs
by blegr 769 days 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...

1 comments

> Most of the time, I want to pass/return a reference

Surprised to hear that you want to return a reference so frequently.

These 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?).

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

It'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.
Ah, that’s unfortunate.
How 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++.

> How else would you implement C++’s vector::operator[] for example?

Are you asking in a theoretical world where it isn’t defined to already return a `T&`?

Now that GP said it, it'd be nice to be able to write "some_map[i].value_or(some_value)".
You can do this in rust with Vec::get, which returns an Option<&T>.
No, that’s my point. It returns a reference. So it’s a good example of when you might want to return a reference, which you said seemed uncommon. But the reference it returns is unsafe (for example, it gets invalidated if the vector is later resized), whereas the reference returned by the corresponding Rust operator is safe.
Sure, but the person I was relying to said they were writing code that returns references (not implementing the standard library). And my surprise was that they have to do it so often.

My overall advice here would be that if you find yourself implementing vector-like data structures very often, then it is time to take a second look the design.

Fair enough, but even if you’re not writing code like this, you still have to use it, so you’re still exposed to the unsafety.