4 ms·
> but offers much less to make using your library pleasant and foolproof Not my experience so far, I might go as far and say it makes it more foolproof because
by volsa_ 4y ago
> but offers much less to make using your library pleasant and foolproof
Not my experience so far, I might go as far and say it makes it more foolproof because when writing your library you have the option to return an `Option` or `Result` enum.
- ncmncm 4y agoOption and Result types are as easily coded in C++. The former is in the Standard C++ library. The latter will be in the next, but anyway the one in Boost has worked fine forever. Throwing, instead, is a choice unavailable to Rust coders, so you often have no alternative but to return these more complicated things that users are then obliged to unpack. A standard macro makes that easier, and is semantically equivalent to throwing, but imposes substantial overhead on successful calls.
- Rusky 4y agoC++'s option and result types are much larger, uglier, and harder to use correctly than Rust's. The shift from throwing to returning a Result is not really an increase in complexity- closer to a reshuffling of syntax. But that's not really all that relevant either, because comparing languages at this level of detail misses the forest for the trees. An interesting comparison takes a step back and compares which problems the languages (try to) solve. Often something that appears to be a clear win for one or the other turns out to be a non-issue.
- ncmncm 4y agoThe substantial performance overhead, in Rust, of code to handle those types is unavoidable, even where source-level inconvenience has been minimized. Overhead is imposed all up and down the call chain, every time through. Seems pretty relevant to me.
- arinlen 4y ago> C++'s option and result types are much larger, uglier, and harder to use correctly than Rust's. What's your rationale for claiming in a swiping generalization that implementing a data type, regardless of all options or approaches and design, has no other option than doing everything wrong?
- Rusky 4y agoI mean, have you looked at them? C++'s standard library optional type is a tagged union implemented from scratch, with a dizzying array of template metaprogramming to meet the standard's requirements- see e.g. Microsoft's here: https://github.com/microsoft/STL/blob/main/stl/inc/optional#L214 https://github.com/microsoft/STL/blob/main/stl/inc/optional#.... This isn't a criticism of the team behind this code, it's just what it takes to do this in C++. Rust gets most of that functionality from the language instead, in a much cleaner way. Sum types are built in, value categories and move semantics are handled automatically, there is little-to-no metaprogramming, and most of the API is just simple convenience combinators with obvious implementations: https://github.com/rust-lang/rust/blob/master/library/core/src/option.rs#L518 https://github.com/rust-lang/rust/blob/master/library/core/s... If nothing else, this is a clear counterexample to the claim that "Option and Result types are as easily coded in C++."
- ncmncm 4y ago> it's just what it takes to do this in C++ False.
- LegionMammal978 4y agoDo you have any examples of how std::optional could be implemented more simply?
- ncmncm 4y agoThe std::optional in MSVC was implemented in a language considerably behind current C++, for obvious reasons. The need to use template metaprogramming in implementations is much less, today.
- LegionMammal978 4y agoHow so? Some of the "enable_if"s can probably be replaced with "requires" syntax, as well as the "conjunction_v"s and "disjunction_v"s, but the majority of the complexity seems to be in expressing the various requirements imposed by the Standard. Are there recently-added concepts (or other features) that would express them more naturally?
- mathstuf 4y agoThe fact that `std::optional<T&>` is verbotten makes them quite a bit more useless. The Boost one is better because it doesn't have this misguided limitation. It's really quite a sad story and a loss to all of C++ that it is this way (and not for lack of trying on ThePhD's part). > no alternative but to return these more complicated things that users are then obliged to unpack Yes, thank you. It is much better this way. I think "substantial overhead" needs to be backed up with some numbers here because setting up exception landing pads is certainly not free.
- chlorion 4y agoAccording to this link (posted below and includes benchmark results and a benchmark you can run), they compared result style error handling with conventional exceptions in C++, and the result style error handling (using an impl of std::expected) was "more than four times slower". According to the link and my understanding, exceptions are essentially "free" at runtime in the non-exceptional case on certain platforms such as Linux, but slower than result style error handling in the exceptional case. I prefer result style error handling personally and I am not suggesting that it's worse or shouldn't be used, just thought the findings were interesting and worth considering. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2544r0.html https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p25...
- mathstuf 4y agoSo I did some testing with Rust and I don't think that the C++ "four times slower" applies to it at first glance. Maybe Rust can just do better optimizations or something because Rust knows that it is a discriminated union, but these kinds of conclusions can't just be ported across languages blindly. Of course, porting the benchmark for `sqrt` wasn't trivial because (of course) C++ just modifies the span passed in making it easy to abstract out the allocations whereas Rust says "you cannot pass a mutable slice across a `catch_unwind` barrier", so all of my tests end up returning a new `Vec` inside the benchmarked function. I also wonder how much using an inner function for `fib` would allow some TCO to kick in and change results again. In any case, I don't think that C++'s has anything that satisfies the use cases that Rust's `Option` or `Result` cover in its standard library, so even if `std::optional` and `std::expected` were magically faster, the fact that `std::optional<inner_field_type const&>` is not supported means I can't use it for what I want anyways and I'm back to Boost or hand-coding classes and dealing with corner cases myself. Which is, unfortunately, a C++-shaped problem that has existed for a long time anyways, so…nothing new.