- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
struct mystream: public std::ostream
{
mystream(std::ostream & o): std::ostream(o.rdbuf()) {}
template <class T>
mystream & operator << (T const & arg)
{
if (enabled_) as_std_ostream() << arg;
return *this;
}
// дерьмо STX
mystream & operator << (std::ostream & (*f)(std::ostream &))
{
if (enabled_) as_std_ostream() << f;
return *this;
}
mystream & operator << (std::ios & (*f)(std::ios &))
{
if (enabled_) as_std_ostream() << f;
return *this;
}
mystream & operator << (std::ios_base & (*f)(std::ios_base &))
{
if (enabled_) as_std_ostream() << f;
return *this;
}
// дерьмо ETX
void enable() { enabled_ = true; }
void disable() { enabled_ = false; }
protected:
bool enabled_;
std::ostream & as_std_ostream() { return *this; }
};
http://liveworkspace.org/code/1AWg24$118
"правильно" это делается на уровне streambuf, перекрывая overflow() (и xsputn()).
"правильно" в ковычках потому что в принципе говно.
подкладывать свой streambuf в поток, который disabled - значит делать все форматирования и тратить на это cpu, чтобы в итоге проигнорить конкретно запись символов - не, не катит
по крайней мере все штатные operator<<() проверяют goodbits прежде чем что либо делать.
... если подумать, то даже и перекрывать ничего не надо:
("\n" вместо std::endl что бы про проверить как что флушится.)
execution time: 3.05
правильно:
я правда про проверку `if (o)` не уверен. по моему опыту когда ставятся fail/eof биты то чистится goodbit. и наоборот. но почему то они все равно разные флаги.
переписывать миллион своих и чужих выводов в поток, теперь проверяющих переданный им ostream& - не вариант
не заморачивайся так сильно, свою проблему я уже решил, и даже сегодня я допёр, почему второй темплейт так и не заработал бы с std::endl
в ГК приведен схематичный пример, в жизни не bool enabled, а более сложная логика
да. хотя на самом деле именно так оно и должно делатся (и в стандартной библиотеке делается), потому что если поток не good, то ему разрешено по стандарту бросать исключения. чего почти никто никогда не ожидает и не обрабатывает.
"не заморачивайся так сильно"
я этим уже не раз по работе заморачивался. меня эта тема больше не напрягает :)
"в ГК приведен схематичный пример, в жизни не bool enabled, а более сложная логика"
у нас это сделано еще "проще." схематично:
что есть compile-time only
может мне было правильней написать `if (!enabled())`.
трюк что это раскрывается в:
и если у тебя есть что-то типа:
то это гарантирует что у тебя эта `BigObject.toString()` даже и не вызовется если ничего выводить не надо.
но недостаток макросов в том, что они рано или поздно начинают конфликтовать с нормальными, человеческими идентификаторами
притом, что в v.1 используется синтаксис вида error() << "hello" << std::endl;
trace() << "verbose description" << std::endl;
и мне бы не хотелось настолько всё сломать
...хм.
:)
шучу шучу. дело вкуса. макросы хороши только тогда когда можно быть увереным в дисциплине коллег их не ломать и ими не злоупотреблять. у нас работает потому что всем поср@ть.
встречается какой-нибудь класс или функция error, и всё летит к чертям
скобки в макросе спасут только наполовину - можно будет хотя бы отличить макрос от части неймспейса и переменных, но это всё равно бомба
срыв покровов
мои компиляторы жаловались, что не могут выбрать и вообще запутались
плюнул и сделал в лоб
ругается потому, что std::endl сама по себе overloaded function, и конкретные указания, какие типы подойдут компилятор выручают
кстати, если std::endl подставить в вариант myaut/LispGovno, то тоже получится ошибка
см мой ответ выше почему
у компилятора в распоряжении как минимум 2 варианта (для charT = char и для charT = wchar_t), а как максимум - бесконечно
явные перегрузки - например, std::ostream & (*f)(std::ostream &) позволяют компилятору подставить в оператор конкретно std::endl<char, char_traits> и поэтому всё работает
сейчас еще попробую кое-что, ради интереса, но не факт, что уже получится меньше кода, как хотелось какой T компилятор должен вывести для первого шаблона, и какое O для второго, если бы тот работал?
тред-сейф логи, работающие в релизе, с настраиваемым в рантайме уровнем логирования для каждого логирующегося класса и настраиванием направления вывода логов (поток, ротация файлов, udp, whatever)
вроде ?