С>Нет, это немного не то. Автор топика хочет, чтобы в дебажной версии были логи, а в релизной нет. Т.е. один дефайн/ундеф — и нету никакого логирования. Или тут тоже как-то можно?
Тут тоже макросами можно.
#ifdef DEBUG
#define TRACE(x) get_trace_stream()<<x
#else
define TRACE(x)
#endif
...
int n;
TRACE("n=" << n);
// в этом случае немного неудобно, но жить можно
TRACE(("someFunc returned "<<someFunc(1,2,3)));
Здравствуйте, Gleb Alexeev, Вы писали:
С>>Нет, это немного не то. Автор топика хочет, чтобы в дебажной версии были логи, а в релизной нет. Т.е. один дефайн/ундеф — и нету никакого логирования. Или тут тоже как-то можно?
GA>Тут тоже макросами можно.
GA>
GA>#ifdef DEBUG
GA>#define TRACE(x) get_trace_stream()<<x
GA>#else
GA>define TRACE(x)
GA>#endif
GA>...
GA>int n;
GA>TRACE("n=" << n);
GA>// в этом случае немного неудобно, но жить можно
GA>TRACE(("someFunc returned "<<someFunc(1,2,3)));
GA>
А можно и по другому макросами (ноги растут отсюда):
Здравствуйте, Gleb Alexeev, Вы писали:
GA>Отличная идея , только я бы std::cout на какой-нибудь null_stream заменил бы (в случае, когда трассировка отключена).
Нет смысла. Ведь никуда ничего не выводится. Эта запись в случае !DEBUG будет эквивалентна:
std::cout;
А std::cout нужен для того, чтобы тип выражения в обоих ветках ?: был одинаковый -- std::ostream & (к примеру, или конкретный тип, к которому принадлежит std::cout).
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, eao197, Вы писали:
E>Здравствуйте, Gleb Alexeev, Вы писали:
GA>>Отличная идея , только я бы std::cout на какой-нибудь null_stream заменил бы (в случае, когда трассировка отключена).
E>Нет смысла. Ведь никуда ничего не выводится. Эта запись в случае !DEBUG будет эквивалентна: E>
E>std::cout;
E>
E>А std::cout нужен для того, чтобы тип выражения в обоих ветках ?: был одинаковый -- std::ostream & (к примеру, или конкретный тип, к которому принадлежит std::cout).
Я через секунду это и сам понял, только удалить не успел . Поставьте мне минус, кто-нибудь, и сорри за шум.
Здравствуйте, Gleb Alexeev, Вы писали:
GA>>>Отличная идея , только я бы std::cout на какой-нибудь null_stream заменил бы (в случае, когда трассировка отключена).
E>>Нет смысла. Ведь никуда ничего не выводится. Эта запись в случае !DEBUG будет эквивалентна: E>>
E>>std::cout;
E>>
E>>А std::cout нужен для того, чтобы тип выражения в обоих ветках ?: был одинаковый -- std::ostream & (к примеру, или конкретный тип, к которому принадлежит std::cout).
GA>Я через секунду это и сам понял, только удалить не успел . Поставьте мне минус, кто-нибудь, и сорри за шум.
Зачем же удалять?
Если что-то может быть истолковано не правильно, оно и будет истолковано неправильно ((С) кажется из законов Мерфи). Может еще у кого-то такой же вопрос возникнет, а тут сразу ответ готов.
... << RSDN@Home 1.1.4 stable rev. 510>>
SObjectizer: <микро>Агентно-ориентированное программирование на C++.
Здравствуйте, Gleb Alexeev, Вы писали:
GA>Здравствуйте, Centaur, Вы писали:
C>>Дальше, оптимизирующий компилятор все обращения к log_print в нелогирующей версии выоптимизирует до нуля. GA>Не факт. GA>Боюсь, оптимизатор может не справиться с таким случаем (для этого компилятору пришлось бы доказать, что ни одна из non_inline_functionX не имеет побочных эффектов; может быть, что глобальная оптимизация с этим и справится, но гарантии нет): GA>
Мы всё ещё говорим о логировании, или уже перешли к минимизирующим поверхность при заданном объёме представителям семейства непарнокопытных в условиях отсутствия атмосферного давления? Какие неинлайновые функции, какие побочные эффекты? Да тут use case примерно следующей сложности:
logstream << "Hello world, we are flying at " << altitude << "m, "
"the temperatures of engines are " << writeContainer(engineTemp, ", ") << "\n";
Никаких неинлайновых функций, большей частью строковые литералы и локальные переменные, изредка конструкторы временных объектов, реализующих ленивую запись в поток. То есть, если нас попросят записаться в std::ostream, то мы запишемся в std::ostream, а если нас (сделают вид, что) запишут в null_stream без нашего участия, то мы и не будем ничего делать.
Здравствуйте, Centaur, Вы писали:
C>Мы всё ещё говорим о логировании, или уже перешли к минимизирующим поверхность при заданном объёме представителям семейства непарнокопытных в условиях отсутствия атмосферного давления? Какие неинлайновые функции, какие побочные эффекты? Да тут use case примерно следующей сложности: C>
C>logstream << "Hello world, we are flying at " << altitude << "m, "
C> "the temperatures of engines are " << writeContainer(engineTemp, ", ") << "\n";
C>
Никаких неинлайновых функций, большей частью строковые литералы и локальные переменные, изредка конструкторы временных объектов, реализующих ленивую запись в поток. То есть, если нас попросят записаться в std::ostream, то мы запишемся в std::ostream, а если нас (сделают вид, что) запишут в null_stream без нашего участия, то мы и не будем ничего делать.
Ну, во-первых, GetLastError у меня обычно вызывается сразу после возникновения ошибки, в конструкторе Win32Exception. Независимо от того, ведём мы логи или не ведём. А FormatMessage — соответственно в Win32Exception::what().
А во-вторых, даже в этом примере я попытаюсь максимально «ленивизировать» операцию — сделав lastErrorMsg классом и унеся всё тяжеловесное в его friend std::ostream& operator<<(std::ostream&, const lastErrorMsg&). В конструкторе останется один GetLastError(), и то только потому, что есть (минимальный) риск этот самый LastError прощёлкать клювом, успешно выполнив Win32API-операцию.
GA>При желании можно придумать и более правдоподобный случай, когда тяжеловесный код будет выполняться впустую при отключенной трассировке.
Здравствуйте, Centaur, Вы писали:
C>Ну, во-первых, GetLastError у меня обычно вызывается сразу после возникновения ошибки, в конструкторе Win32Exception. Независимо от того, ведём мы логи или не ведём. А FormatMessage — соответственно в Win32Exception::what().
C>А во-вторых, даже в этом примере я попытаюсь максимально «ленивизировать» операцию — сделав lastErrorMsg классом и унеся всё тяжеловесное в его friend std::ostream& operator<<(std::ostream&, const lastErrorMsg&). В конструкторе останется один GetLastError(), и то только потому, что есть (минимальный) риск этот самый LastError прощёлкать клювом, успешно выполнив Win32API-операцию.
С чего начали:
Замена log_stream на null_stream заставит оптимизатор полностью выкинуть код трассировки из приложения.
Чем закончили:
Я, нижеподписавшийся Centaur, лично никогда не вызываю не-inline функций при трассировке .
Удобство макросов типа ASSERT и TRACE в том, что их пишешь не задумываясь о стоимости, зная, что в релиз ничего из отладочного кода не попадет. Вы же призываете пользователя log_stream к дисциплине, ограничивая его удобство без особой на то причины (ниже ув. тов. eao197 дал более элегантное решение), тем более, что не-inline функция может не вызываться явно в выражении записи в поток.
C>Пока не убеждён
Ладно, другой пример:
С>Нет, это немного не то. Автор топика хочет, чтобы в дебажной версии были логи, а в релизной нет. Т.е. один дефайн/ундеф — и нету никакого логирования. Или тут тоже как-то можно? С>И под C не покатит, так что может оно и лучше, но не так универсально.