Basically think about the state of c++ and c++ compilers two decades ago. I wouldn’t be surprised if that factored into it.
As others have said codesize can also be an issue - it’s super easy to make templates produce insane amounts of code, especially in older compilers.
Eliminating code bloat with templates requires careful judgment about where to put type erasure and how to factor your code
Just like everything else, it's a time/space tradeoff because it generates less optimal code in exchange for a smaller binary size.
So even if the linker fails to de-dupe, you're still able to manually fix it pretty easily without giving up on templates entirely.
But libkern predates C++11, so decisions made by that team at that time are largely obsolete and should be heavily re-evaluated rather than blindly followed.
You can’t really just say “update to a newer version of the language” when you have both API and ABI compatibility constraints.
For source you can deprecate APIs, etc so future versions would have an early warning the source changes would be necessary.
But that doesn’t help shipping kexts, for that you need ABI stability, which really puts the hammer on changing/updating the features that you use. Many of the C++ features cause exciting binary compatibility problems, and make it super easy to accidentally change the ABI :-/
That aside yes, you totally can just update to a newer version of the language. If you are trying to maintain C++ ABI stability then your life is harder, yes, but it's no harder than it already is when you just upgrade compilers or deal with people building with other compilers (and most everyone ships C ABIs anyway to avoid this entire category of problems - extern "C" still works great in C++17). But you are still completely free to use newer features in the implementation itself which doesn't impact API or ABI stability in the slightest.