В C ++ 11 вы можете использовать замыкание.У вас будет что-то вроде:
trace.Trace(LEVEL_INFO, [&](){ return format("x is %i") % ExpensiveWayToGetX(y, z); }, some_props);
В C ++ 03 вы можете использовать хак boost.lambda для аналогичного эффекта.
Однако, имея макрос, обертывающий if(trace.CanTrace(...)) trace.Trace(...)
все еще немного эффективнее, потому что он даже не инициализирует объект со всеми ссылками, которые понадобятся закрытию, если не включена трассировка.Я предлагаю объединить макрос с интерфейсом потока, чтобы вы имели
#define TRACE(level, some_props) \
if(!trace.CanTrace(level, some_props)) 0; \
else trace.Trace(level, some_props)
и называли его как
TRACE(LEVEL_INFO, some_props) << "x is " << ExpensiveWayToGetX(y, z);
или определяли operator()
вместо operator<<
и для printf-стандартное форматирование:
TRACE(LEVEL_INFO, some_props)("x is %i", ExpensiveWayToGetX(y, z));
Если не включено, чем 0, иначе фактически есть трассировка, так что она не сгорает, если вы когда-нибудь напишите:
if(IsSomethingWrong())
TRACE(LEVEL_WARNING, some_props) << WhatIsWrong() << " is wrong";
else
DoSomething();
(без макроса else, остальное после того, как оно перейдет в if внутри макроса, но с этим else, оно будет правильно проанализировано)