That said I absolutely don't disagree with you at all. It's really a bit silly C doesn't have it at this point. `gcc` will happily do all of this math for you at compile time even if you do as much of the math as you can in `static` functions. But to make it compile you have to declare `pixels` in `main` because you can't call the functions in the initializer for file-scoped variables - even though the compiler can already optimize them out.
More to the point, constexpr would be a heck of a lot more efficient - changing M4 to M5 increases the preprocesed size from 80 MB to 240 MB. This is an exponential increase, despite that a Mandlebrot pixel can be computed in linear time. (Linear to the maximum number of steps.)
I suspect that this is because if you write a macro and use your macro argument twice, this doubles the length of whatever your macro argument was.
yes, some people have written entire constexpr raytracers for instance : https://github.com/tcbrindle/raytracer.hpp