That is still thin by the modern standard. More accurately speaking, C++ standard library has too many useless things and lacks too many useful things. Compare with D [1], Rust [2] or Zig [3].
It looks like the only big feature any of these standard libraries contain that C++ doesn't are things like networking and json/xml parsers. I would argue that those should not be part of a standard library, but you can still easily get those through additional C/C++ libraries.
I honestly don't know what else you would be looking for in a standard library. C++ provides out of the box:
- hash maps
- sets
- dynamic arrays
- fixed length arrays
- bit sets
- option types
- atomics
- mutexes
- futures
- strings
- queues/stacks/Deques
- tuples
- variants
- streams
- etc
In addition, they have a huge range of algorithms that operate on all of these containers. I'm really curious, what does the standard library not have that you think forces you to write boilerplate?
To be useful, option types and tuples need language support. C++ doesn't have it.
Similarly, to be useful, futures need runtime support i.e. asynchronous I/O. They also need language support like async-await, to generate these state machines. C++ has none of them.
The standard library still does not really support Unicode, people need third-party libraries like ICU just to manipulate strings: https://stackoverflow.com/q/42946335/126995
I believe Rust has the most conservative standard library among those modern languages and it still has many things that the C++ standard library simply don't have (yet):
- Unified result types. C++23 is finally going to have `std::expected`, but it will probably take another version or two to see the `std::expected`-only version of standard library.
- Iterator utilities. Again, C++23 will see a significant improvement in <ranges> but that still falls short of what Rust `Iterator` provides by default.
- Checked arithmetic. Rust and many other languages distinguish checked and unchecked arithmetic and put one of them (typically unchecked one) into the standard library. C++ doesn't have anything like that.
- Guarded mutex (that is, a portion of memory by design only accessible when locked) and concurrent queue. C++ does support concurrency out of the box, but its tools are pretty bare bones and this is one example.
Thanks for providing some specific examples! I still don't see how any of these would result in a 30% decrease in boilerplate. My main point was I feel like header files are the biggest piece of boilerplate and it seems weird to accuse the lack of features in the standard library as a reason for all the boilerplate.
Just a couple other points though, C++ provides fully customizable iterators. They don't have ranges, but ime the amount of times I need ranges vs just iterating over a container are relatively low. Also, is a lock guard in C++ not the same thing as a guarded mutex? This may be ignorance on my part because I'm not familiar with rust, but it sounds like the same thing to me. A lock guard will lock and automatically release a mutex once it goes out of the current scope.
You have a good point that featureful standard library doesn't necessarily result in less boilerplate, but I assumed that you kinda implied it by enumerating features. Frankly almost every feature you and I listed is not exactly relevant here---most of them can be easily refactored into external libraries ;-)
What I find most lacking from the C++ standard library is actually coherence. Different parts of standard library were developed separately from each other, and while adapters between them exists (e.g. stream iterators can be used with `std::format_to`) they are by definition boilerplates. Some parts are simply not relevant in the modern C++ programming and still have to be retained for compatibillity (e.g. `std::auto_ptr`). In this view C standard library is actually a lot more coherent than C++, even though C standard library itself is less powerful and featureful than C++.
> They don't have ranges, but ime the amount of times I need ranges vs just iterating over a container are relatively low.
I think this is simply because C++ iterators are less usable. All iterators can be technically rewritten as loops, so you may have internalized to avoid using iterators when iterators would be beneficial but difficult to use. I personally find myself using iterators a lot more in Rust than in C++.
> Also, is a lock guard in C++ not the same thing as a guarded mutex? This may be ignorance on my part because I'm not familiar with rust, but it sounds like the same thing to me. A lock guard will lock and automatically release a mutex once it goes out of the current scope.
I actually don't know the exact term (the name "guarded mutex/lock" was what I've used in the past), but I meant a mutex that is strongly coupled with some additional data so that the API prevents or at least discourages to access the data without acquiring the mutex. In a hypothetical design `std::mutexed<T>` will be `T` plus `std::mutex` and `std::lock_guard<std::mutexed<T>>` would have `operator *` which allows the access to `T`. In Rust [1] this is actually the default, and you never have a bare `std::mutex` (though it can be simulated with placeholder data, `Mutex<()>`).
> You have a good point that featureful standard library doesn't necessarily result in less boilerplate, but I assumed that you kinda implied it by enumerating features.
Gotcha, I appreciate the back and forth which helped me to clarify that point a bit better :)
> What I find most lacking from the C++ standard library is actually coherence.
I 100% agree. There are plenty of areas that C++ is very lacking, and I think this comment highlights that.
I initially started this thread off because a big complaint I hear among C++ users is the language is a bloated mess, which is why the parent comment saying that C++ had a thin standard library didn't ring true to me. But I think what you're saying here is closer to the truth. It has a lot of good features, but they're mostly after thoughts and poorly integrated. Whereas a language like Rust (or another modern language) has around the same amount of features builtin, but they're more focused, integrated, and planned :)
I think it makes sense to bundle with a standard module things which are quite OS independent and very commonly used like Python, Go, Swift, Julia and many other languages do: collections, common algorithms, File reading and writing, socket communication, async, concurrency, JSON and possibly simple XML. String manipulation, regular expressions.
What should clearly be outside is stuff like graphics library, GUI, HTML.
> collections, common algorithms, File reading and writing, socket communication, async, concurrency, JSON and possibly simple XML. String manipulation, regular expressions
C++ does provide all of this in the standard library except for sockets, Json and XML. I think once you get to things like Json and XML it doesn't make much sense to include that in the standard library. There are plenty of applications that don't need or use either of those, and it's a shame to bundle some configuration language when somebody may have another preference like yaml or something. There's nothing wrong with providing additional standard add-ons that include these, but I definitely don't think it makes a lot of sense to bundle it in with the standard.
This is a whole separate conversation, but my main point was there are a lot of better things to pick on C++ for. Most complaints I hear are that it includes too many useless features haha.
[1] https://dlang.org/phobos/
[2] https://doc.rust-lang.org/std/
[3] https://ziglang.org/documentation/master/std/