Moreover, because of `#define`s, the effect of including a file can be entirely different, so a compiler can never say "Oh, I know what's in this include file already, I don't need to include it again in other translation units".
Of course #define's have many uses, and at present cannot be avoided entirely, but C++ has been making an effort to have other mechanisms put in place so as to obviate the use of #define's
In particular, look for CppCon talks about Modules.
In a nutshell: Using compile-time facilities which are within the language itself. Compilers will expose information about the platform, about themselves, etc.
A couple of examples:
* https://en.cppreference.com/w/cpp/utility/source_location
* https://en.cppreference.com/w/cpp/types/endian
> can you build big projects across clang/g++/intel without preprocessor workarounds now?
Well, first of all, s/now/when C++20 is fully and widely adopted.
Still, a good question. Possibly not? I'm not sure. But you would need a lot less of them than previously.
> has the number of viable compilers in use dropped
Not really.
> and compatibility amongst those that live on increased?
Well, if they're compatible with the standard, that says more than it used to.
> how about stuff like debugging/instrumentation?
Maybe if constexpr(in_debug_mode) ? Not sure. I'm not on the committee...