It can be a trade-off, but becoming less and less so. I'll admit to not looking at the implementation, but when you sell it as "modern" then it's not OK to do it for performance, for example.
And almost every single use I've seen "for performance" actually has zero or negligible performance impact.
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...