Приложение имеет систему ведения журнала, которая позволяет включать или отключать функции ведения журнала своих модулей во время выполнения. Команды журнала принимают потоки на входе (что является безопасной альтернативой "sprintf", вряд ли будет более неприятная ситуация, чем если ваша система отладки является причиной сбоя.
Проблема заключается в том, что если я выполняю такие вещи, как:
logger.Trace << "Requests pending:" << buffer.findRequests();
и findRequests()
имеет высокую вычислительную сложность, даже если отключить уровень журнала трассировки для модуля, поиск будет выполняться (при сборке потока) до его отклонения внутри метода Trace operator<<
.
Очевидной альтернативой было бы засорять код:
if(logger.Trace.Enabled()) logger.Trace << ...
Это некрасиво и это не удобно. Я мог бы заменить его макросом, используя if
, или тот, который использует короткое замыкание &&
, будучи несколько более приятным (может использоваться как RValue, которое после потоковой философии возвращает bool false в отключенном потоке):
#define TRACE if(logger.Trace.Enabled()) logger.Trace
#define TRACE dummyLogVar = logger.Trace.Enabled() && logger.Trace
Ни один из них не является особенно красивым или безопасным. Сотрудник предложил закрыть:
logger.Trace([&](f){f << "Requests pending:" << buffer.findRequests();});
.Trace
будет оценивать закрытие только в том случае, если этот уровень включен. Логично, что приятно, но синтаксически абсолютно ужасно. Ввод этого беспорядка: logger.Trace([&](f){f <<
... ;});
сотни раз?
Есть ли более аккуратный, безопасный и удобный способ предотвращения оценки потока?