The short answer is that it is not C++. The longer answer can be derived by looking at the list of language features used, in a representative Rust or C++ hash library, that C lacks. We may guess that a few of those are not strictly necessary. Still, the list is quite long.
Ultimately, the answer is that C is not designed for abstraction, expressing things that should occur at compile time, but rather just to map closely to instructions that machines that existed in the 1970s offered. It does that. Its offerings for compile-time behavior amount to, mostly, the preprocessor, which understands nothing at all of language semantics, never mind types.
Oddly, Rust's macro language also doesn't know from types.
Ultimately, the answer is that C is not designed for abstraction, expressing things that should occur at compile time, but rather just to map closely to instructions that machines that existed in the 1970s offered. It does that. Its offerings for compile-time behavior amount to, mostly, the preprocessor, which understands nothing at all of language semantics, never mind types.
Oddly, Rust's macro language also doesn't know from types.