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