|
|
|
|
|
by hvdijk
1350 days ago
|
|
Sure, std::optional<int> is unlikely to result in such behaviour in practice, and std::optional<int*> is likely to "only" result in such behaviour if the result of operator*() is dereferenced again, despite both already being UB. Think of non-POD types, such as std::optional<std::string>, though: when you end up using uninitialised std::string objects, things do break in practice because of pointers used internally to implement std::string, and badly so. The fact that checked versions exist but are not used by default, have to be explicitly opted into, is consistent with C++'s designs and may be used to defend the current design, but at the same time also means it describing std::optional as memory-unsafe becomes a valid opinion based on facts, I think. |
|
But your "facts" are "if I use the API wrong, it behaves wrong." But std::optional isn't easy to accidentally misuse here, unlike string_view (an actually "unsafe" addition). The argument that optional is broken if you both don't use has_value and don't use any of the other helpers (like value_or() or value() or transform or etc...) then it has UB means that optional is "broken by design" is not a very strong position to take.
It's hard to imagine this being a problem in practice. It's pretty encoded in the code that it's optional, to just completely ignore that and blindly access it anyway seems pretty self-evident as a usage issue. Yes bugs happen, but come on. This is not a particularly sharp edge in C++'s toolbox here. It's a pretty straightforward, intuitive type, doing pretty much exactly what it says it does, exactly how you'd expect it to do.
Should operator->() and value() be swapped? maybe, but then it'd be inconsistent with std::vector & other older types. And that inconsistency is probably worse overall.