1. C++ / Говнокод #12746

    +23

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    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, 13 Марта 2013

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

    • А что мешает использовать std::function?

      http://liveworkspace.org/code/1AWg24$118
      Ответить
      • тоже говно. ну да 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 что бы про проверить как что флушится.)
            Ответить
            • вывода не будет, но затраты на форматирование будут всё равно.
              Ответить
            • http://liveworkspace.org/code/4zuvx7$1
              execution time: 3.05
              Ответить
              • так и тоже самое будет с кодом в ГК - если ты конечно не перекроешь и этот новый 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;
                    Ответить
                    • > #define whateverstream
                      что есть compile-time only
                      Ответить
                      • нет. с чего ты взял?

                        может мне было правильней написать `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(). то что я делал была унификация этого всего что бы можно было одним свитчем это контролировать.
                    Ответить
      • хуясе... 118 ревизия:)
        Ответить
        • походу, это тайный испытательный полигон LispGovno
          срыв покровов
          Ответить
    • А с чем шаблонное ограничение связано?
      Ответить
      • сам не знаю
        мои компиляторы жаловались, что не могут выбрать и вообще запутались
        плюнул и сделал в лоб
        Ответить
        • аа.. теперь очевидно
          ругается потому, что std::endl сама по себе overloaded function, и конкретные указания, какие типы подойдут компилятор выручают
          кстати, если std::endl подставить в вариант myaut/LispGovno, то тоже получится ошибка
          Ответить
    • А что только первого варианта (перед дерьмом) не хватает, внутри же всё одинаковое, или это заглушки?
      Ответить
      • не работал << std::endl;
        см мой ответ выше почему
        Ответить
        • Не вкуриваю, чем 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)
            Ответить
        • > говномакросах
          вроде
          LOG(Info) << "It is quiet in Bagdad";
          ?
          Ответить
    • Во было бы круто сериализовывать функции в стрём и отправлять их по сети.
      Ответить

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