> giving up on many desirable features of software projects
Some C++ libraries are header only because they were designed for highest performance possible.
Classic example is std::sort versus qsort, C++ usually wins because inlining.
My favorite example is Eigen, they use template metaprogramming to save RAM traffic. When you write x=a+b+c for matrices or vectors, the library doesn't compute a+b intermediate vector. That C++ expression returns a placeholder object of a weird type, CPU computes a+b+c in a single loop over them, reading a,b,c, and writing to x.
Features are header only for performance. Entire libraries are rarely header only for that reason. Typically it's more for ease of consumption, but there are other major drawbacks to that approach, like having the widest possible API and ABI, making long term maintenance harder.
For instance, on some platforms system headers use preprocessor variables called "major" and "minor". If your code is in source files, you have strong control over whether you care. If your code is all in headers, your don't since all your code is affected by unrelated textual inclusions.
> having the widest possible API and ABI, making long term maintenance harder.
For cases where it matters, C++ can do that just fine.
Look at Direct3D, DirectWrite, Media Foundation. They're written in OO C++, and they use IUnknown ABI from COM. They're not COM objects, the ABI is the only feature they took from there.
Apparently, C++ library developers don't care enough.
> you basically give up on a stable narrow interface when shipping header only.
I agree.
But in some cases, you also gain performance not achievable with stable interfaces.
It’s about tradeoffs.
I think modern C++ needs stable ABI and well-isolated modules less than it did 10-20 years ago. 20 years ago people wrote everything in C++. Now C++ lost the majority of the market to higher level and safer languages, it’s only used for components where performance really matters. For such components, runtime overhead of stable ABIs sometimes matters.
Some C++ libraries are header only because they were designed for highest performance possible.
Classic example is std::sort versus qsort, C++ usually wins because inlining.
My favorite example is Eigen, they use template metaprogramming to save RAM traffic. When you write x=a+b+c for matrices or vectors, the library doesn't compute a+b intermediate vector. That C++ expression returns a placeholder object of a weird type, CPU computes a+b+c in a single loop over them, reading a,b,c, and writing to x.