Большинство злоупотреблений препроцессором происходит из-за недопонимания, цитируя Пола Менсонида (автор библиотеки Boost.Preprocessor ):
Практически все вопросы, связанные со злоупотреблением препроцессоромПроисходит от попытки заставить объектоподобные макросы выглядеть как постоянные переменные, а вызовы функций как макросов выглядят как вызовы функций базового языка.В лучшем случае корреляция между вызовами функций в виде макросов и вызовами функций должна быть случайной.Это никогда не должно считаться целью.Это принципиально нарушенный менталитет.
Поскольку препроцессор хорошо интегрирован в C ++, его легче размыть, и большинство людей не видят разницы.Например, попросите кого-нибудь написать макрос, чтобы сложить две цифры вместе, большинство людей напишет что-то вроде этого:
#define ADD(x, y) ((x) + (y))
Это совершенно неправильно.Запускает это через препроцессор:
#define ADD(x, y) ((x) + (y))
ADD(1, 2) // outputs ((1) + (2))
Но ответом должно быть 3, так как добавление 1 к 2 равно 3. Тем не менее вместо этого пишется макрос для генерации выражения C ++.Мало того, это можно рассматривать как функцию C ++, но это не так.Вот где это ведет к злоупотреблениям.Он просто генерирует выражение C ++, и функция - гораздо лучший способ.
Кроме того, макросы вообще не работают как функции.Препроцессор работает через процесс сканирования и расширения макросов, который сильно отличается от использования стека вызовов для вызова функций.
Бывают ситуации, когда для макросов может быть приемлемо генерировать код C ++, если это не так.Размытые линии.Так же, как если бы вы использовали Python в качестве препроцессора для генерации кода, препроцессор может делать то же самое, и имеет то преимущество, что ему не требуется дополнительный шаг сборки.
Кроме того, препроцессор можно использовать с DSL, например здесь и здесь , но эти DSL имеют предопределенную грамматику в препроцессоре, которую он использует для генерации C ++код.На самом деле это не размывает линии, поскольку использует другую грамматику.