Hacker News new | ask | show | jobs
by Rusky 1369 days ago
C++'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.

2 comments

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

I 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#.... 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/s...

If nothing else, this is a clear counterexample to the claim that "Option and Result types are as easily coded in C++."

> I mean, have you looked at them?

Last time I looked at Rust's std::Result, it's implemented as a tagged union.

Most of C++'s implementations of a Result data type are implemented as tagged unions as well.

What's your point?

> This isn't a criticism of the team behind this code, it's just what it takes to do this in C++.

The only conceivable argument you can possibly make is argue that Rust might support tagged unions as language primitives, but that would be totally pointless as Result types are relevant for the interfaces and higher level abstraction they provide, not your personal opinion of how hard someone else had to work to implement them.

I've developed Result and Either types in a few languages, including C++, and the only hard thing about C++ is doing the usual homework to handle lvalur/revalue/revalue well.

> it's just what it takes to do this in C++

False.

Do you have any examples of how std::optional could be implemented more simply?
The 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.
How 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?
The 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.