I agree on the practicality aspect. When programmimg in C, one learns to accept these preprocessor hacks.
When programming in C++, where limited compile and type metaprogramming exists, one is constantly hitting the limits and it causes endless frustration. I go through a mini cycle of grief until I give in and use a macro, or an otherwise less elegant implementation.
You're right in that it has taken years (decades, even) to standardise some better alternatives to macros. But even now C++ lacks some of their power.
I have to wonder how much faster alternatives would have been implemented, if macros weren't "good enough" for so many use cases.