Я считаю, что хоть в каком-нибудь виде, но препроцессор необходим. Например, в заголовочных файлах Windows при определении различных констант и т.д часто определение зависит от версии Windows для которой компилируется программа, от того 32 битная или 64 битная программа, UNICODE или нет.
Вот кусок кода из WinUser.h
## Код:
```
#if (_WIN32_WINNT >= 0x0500)
#define WM_MOUSELAST                    0x020D
#elif (_WIN32_WINNT >= 0x0400) || (_WIN32_WINDOWS > 0x0400)
#define WM_MOUSELAST                    0x020A
#else
#define WM_MOUSELAST                    0x0209
#endif /* (_WIN32_WINNT >= 0x0500) */
```

Все эти комбинации по разным модулям разнести практически невозможно, так получится "комбинаторный взрыв".
Вот как раз для таких случаев был бы полезен препроцессор.