Кресты / Говнокод #12746 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
  36. 36
  37. 37
  38. 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; }
};

а так хотелось хоть сегодня рыбки поесть захерачить вместо трёх перегрузок
template <class O>
mystream & operator << (O & (*f)(O &)) { ...

Запостил: defecate-plusplus defecate-plusplus, (Updated )

Комментарии (34) RSS

    • тоже говно. ну да STLные стримы в принципе говно.

      "правильно" это делается на уровне streambuf, перекрывая overflow() (и xsputn()).

      "правильно" в ковычках потому что в принципе говно.
      Ответить
      • нет, тут надо именно так сделать, а не через streambuf
        подкладывать свой streambuf в поток, который disabled - значит делать все форматирования и тратить на это cpu, чтобы в итоге проигнорить конкретно запись символов - не, не катит
        Ответить
        • на уровне srteambuf при записи можно вернуть EOF, который все операции вывода на уровне stream'а просто заблокирует.

          по крайней мере все штатные operator<<() проверяют goodbits прежде чем что либо делать.

          ... если подумать, то даже и перекрывать ничего не надо:
          #include <iostream>
          #include <iomanip>
          
          int main()
          {
                  std::cout << "Hello World!\n";
                  std::cout.setstate( std::ios::failbit );
                  std::cout << "Hello World! 2\n";
                  std::cout.clear();
                  std::cout << "Hello World! 3\n";
                  return 0;
          }


          ("\n" вместо std::endl что бы про проверить как что флушится.)
          Ответить
          • вывода не будет, но затраты на форматирование будут всё равно.
            Ответить
            • так и тоже самое будет с кодом в ГК - если ты конечно не перекроешь и этот новый operator<<().

              правильно:
              struct foo {
                 friend std::ostream & operator << (std::ostream & o, foo const &)
                 {
                    if (o) {
                       boost::this_thread::sleep(boost::posix_time::seconds(3));
                    }
                    return o;
                 }
              };


              я правда про проверку `if (o)` не уверен. по моему опыту когда ставятся fail/eof биты то чистится goodbit. и наоборот. но почему то они все равно разные флаги.
              Ответить
              • так ведь там и так уже это перекрыто: template <class T>...

                переписывать миллион своих и чужих выводов в поток, теперь проверяющих переданный им ostream& - не вариант

                не заморачивайся так сильно, свою проблему я уже решил, и даже сегодня я допёр, почему второй темплейт так и не заработал бы с std::endl
                в ГК приведен схематичный пример, в жизни не bool enabled, а более сложная логика
                Ответить
                • "переписывать миллион своих и чужих выводов в поток..."

                  да. хотя на самом деле именно так оно и должно делатся (и в стандартной библиотеке делается), потому что если поток не good, то ему разрешено по стандарту бросать исключения. чего почти никто никогда не ожидает и не обрабатывает.

                  "не заморачивайся так сильно"

                  я этим уже не раз по работе заморачивался. меня эта тема больше не напрягает 🙂

                  "в ГК приведен схематичный пример, в жизни не bool enabled, а более сложная логика"

                  у нас это сделано еще "проще." схематично:
                  #define whateverstream   if(!enabled) {} else getWhateverStream()
                  // ...
                  whateverstream  << foobar;
                  Ответить
                    • нет. с чего ты взял?

                      может мне было правильней написать `if (!enabled())`.

                      трюк что это раскрывается в:
                      if(!enabled()) {} else getWhateverStream() << foobar;


                      и если у тебя есть что-то типа:
                      if(!enabled()) {} else getWhateverStream() << BigObject.toString();


                      то это гарантирует что у тебя эта `BigObject.toString()` даже и не вызовется если ничего выводить не надо.
                      Ответить
                      • я тебя понял
                        но недостаток макросов в том, что они рано или поздно начинают конфликтовать с нормальными, человеческими идентификаторами
                        притом, что в v.1 используется синтаксис вида error() << "hello" << std::endl;
                        trace() << "verbose description" << std::endl;
                        и мне бы не хотелось настолько всё сломать
                        Ответить
                        • "и мне бы не хотелось настолько всё сломать"

                          ...хм.
                          #define error()   if(!isErrorStreamEnabled()) {} else getErrorStream()
                          #define trace()   if(!isTraceStreamEnabled()) {} else getTraceStream()

                          🙂
                          шучу шучу. дело вкуса. макросы хороши только тогда когда можно быть увереным в дисциплине коллег их не ломать и ими не злоупотреблять. у нас работает потому что всем поср@ть.
                          Ответить
                          • я же говорю, рано или поздно
                            встречается какой-нибудь класс или функция error, и всё летит к чертям
                            скобки в макросе спасут только наполовину - можно будет хотя бы отличить макрос от части неймспейса и переменных, но это всё равно бомба
                            Ответить
                • а да. к слову. я только что вспомнил почему мне надо было трахатся на уровне стрима/стримбуфа: у нас где-то только 80% когда используют `<<` (и вдобавок используют вот тот схематично обрисованый define) - остальные делают sprintf() + ostream::write(). то что я делал была унификация этого всего что бы можно было одним свитчем это контролировать.
                  Ответить
    • сам не знаю
      мои компиляторы жаловались, что не могут выбрать и вообще запутались
      плюнул и сделал в лоб
      Ответить
      • аа.. теперь очевидно
        ругается потому, что std::endl сама по себе overloaded function, и конкретные указания, какие типы подойдут компилятор выручают
        кстати, если std::endl подставить в вариант myaut/LispGovno, то тоже получится ошибка
        Ответить
  • А что только первого варианта (перед дерьмом) не хватает, внутри же всё одинаковое, или это заглушки?
    Ответить
      • Не вкуриваю, чем std::endl не подходит в первый шаблон "T const & arg"?
        Ответить
        • тем что он
          template <class charT, class traits>
          basic_ostream<charT,traits>& endl(basic_ostream<charT,traits>& os);
          какой T компилятор должен вывести для первого шаблона, и какое O для второго, если бы тот работал?
          у компилятора в распоряжении как минимум 2 варианта (для charT = char и для charT = wchar_t), а как максимум - бесконечно
          явные перегрузки - например, std::ostream & (*f)(std::ostream &) позволяют компилятору подставить в оператор конкретно std::endl<char, char_traits> и поэтому всё работает

          сейчас еще попробую кое-что, ради интереса, но не факт, что уже получится меньше кода, как хотелось
          Ответить
  • Совершенно не понимаю, кому эта ерунда могла понадобится?
    Ответить
      • Накладите потом пример кода, использующего ваш успешный вариант логов. Не понял что вы запланировали сделать и как это потом использовать.
        Ответить
        • я не запланировал сделать, я переделываю, v.2, так сказать
          тред-сейф логи, работающие в релизе, с настраиваемым в рантайме уровнем логирования для каждого логирующегося класса и настраиванием направления вывода логов (поток, ротация файлов, udp, whatever)
          Ответить
  • Во было бы круто сериализовывать функции в стрём и отправлять их по сети.
    Ответить

Добавить комментарий

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8