| The arrow operator is just a terrible idea, and it's weird that people defend it. It makes sense that C did this, it was a long time ago and compilers weren't very smart so C needs to make up for that, in C++ it's just carried over from C. The absence of default args is a deliberate choice, notice that Rust does have default type arguments in polymorphism, the absence of defaults for function parameters -- which would be technically easy to implement -- reflects a belief which I've come to agree with that overloading is a bad idea, and defaults most often in practice mean you're overloading. For example, C++ std::ranges::binary_search uses defaults to present what are in effect at least two distinct features, as a single function, suiting C++ sensibilities, whereas Rust reflect almost the same capabilities as three functions []::binary_search []::binary_search_by and []::binary_search_by_key For a very simple binary search, things seem pretty similar. In Rust we have a single parameter, for our searched-for element, and in C++ we can stop after that parameter, leaving the comparison function and projection as default for similar effect. However for binary_search_by the C++ is contorted by this API shape. Instead of a callable to decide whether our search found what it was looking for, and if not where it is relative to the searched-for element, the C++ is obliged to carry that element (because it was an earlier parameter) even if it's unused - and then a comparison function which takes the element, and only then optionally a projection which you may or may not use. And for binary_search_by_key the C++ is even more awkward, we have a good reason to use a value here, but we're obliged to specify the comparison function even though we only want to write a callable to make suitable keys (ie a projection), because of the order of the parameters. These would be better served, as in Rust, by three distinct functions, with only the appropriate parameters for each function - even if you choose to actually implement the simplest in terms of the others, because of the documentation and the API shape afforded if you think about it as three things not one with defaults carefully tailored to allow all three uses. Variadics is a genuinely useful feature, but to do it properly is very difficult, C++ 98 doesn't have anything better than Rust [C compatibility, with no real type checking], C++ 11 does have the outline of what you'd actually want, and C++ 17 has much closer to what I'd want to see in Rust some day. Much of what you're thinking of in "weak generics" is probably deliberate constraints to only allow coherent things, in C++ they don't care if you want to make a Foo<NaN> even though that's nonsense, IFNDR gives them the ultimate out, your program has no defined meaning, so too bad. There are some obvious things Rust wants to have but doesn't yet in this space, including broader const Generics (e.g. my OnewayEqual ought to be Oneway<Ordering::Equal>) but it's not going to pursue the irrational C++ exuberance because it's so quickly unsound. C++ doesn't care about that while Rust does. |