Проблема преобразования этого конкретного макроса в функцию заключается в том, что такие вещи, как "The X value = " << x
, не являются допустимыми выражениями.
Оператор <<
является левоассоциативным, что означает что-то в форме A << B << C
рассматривается как (A << B) << C
.Перегруженные операторы вставки для iostreams всегда возвращают ссылку на один и тот же поток, чтобы вы могли выполнять больше операций вставки в одном и том же операторе.То есть, если A
является std::stringstream
, поскольку A << B
возвращает A
, (A << B) << C;
имеет тот же эффект, что и A << B; A << C;
.
Теперь вы можете передать B << C
в макроспросто хорошо.Макрос просто обрабатывает его как набор токенов и не беспокоится о том, что они значат, пока не будет выполнено все подстановка.В этот момент может сработать лево-ассоциативное правило. Но для любого аргумента функции, даже если он встроенный и шаблонный, компилятору необходимо выяснить, каков тип аргумента и как найти его значение.Если B << C
недопустимо (поскольку B
не является ни потоком, ни целым числом), ошибка компилятора.Даже если B << C
является действительным, поскольку параметры функции всегда оцениваются перед чем-либо в вызываемой функции, вы в конечном итоге получите поведение A << (B << C)
, которое здесь не то, что вам нужно.
Если вы 'Желая изменить все виды использования макроса (скажем, использовать запятые вместо <<
токенов или что-то вроде предложения @ svenihoney), есть способы сделать что-то.Если нет, то этот макрос просто нельзя рассматривать как функцию.
Я бы сказал, что в этом макросе нет никакого вреда, поскольку все программисты, которые должны его использовать, будут понимать, почему в строкеначиная с DEBUG_LOG
, они могут увидеть ошибки компилятора, относящиеся к std::stringstream
и / или logger::log
.
Если вы храните макрос, ознакомьтесь с ответами на часто задаваемые вопросы по C ++ 39.4 и 39,5 за хитрости, чтобы избежать нескольких неприятных способов, такие макросы могут удивить вас.