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

    +28

    1. 1
    2. 2
    3. 3
    4. 4
    5. 5
    6. 6
    7. 7
    8. 8
    std::string toString(std::function<std::string(T)> f = std::function<std::string(T)>()) {
       std::stringstream ss;
       if(f)
          ss << f(some_value);
       else
          ss << some_value;
       return ss.str();
    }

    Запостил: an0nym, 03 Октября 2012

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

    • А почему в строках 3-4 не просто return f(some_value)?
      И вообще - если функция f принимает нужный тип и возвращает строку, и делает всю необходимую работу, нахрена вызывать ее опосредованно через toString?
      Ответить
      • Это контейнер. Если T - нестандартный тип или указатель, в stringstream его не загонишь, а для обычных типов каждый раз указывать функцию глупо.
        Ответить
        • Таки вывод f можно бы было сделать, например через перегрузку функций от типа T на шаблонах.
          Ответить
        • Так если some_value имеет нестандартный тип T, не имеющий оператора << для стримов, оно же не скомпилируется из-за ss << some_value?
          Ответить
          • Да, вы правы. Это не D со static_if.
            Ответить
            • бюрократы из комитета утверджают, что это ненужно
              Ответить
              • Они просто на крестах давно не писали и не собираются, поэтому им это не нужно, ага.
                Ответить
                • да может быть они и правы
                  судя по тому, что новый стандарт с легкостью был заимплеменчен вендорами за считанные недели после публикации
                  Ответить
                  • Что-что, а std::none не требует ничего нетривиального. А static_if конечно...
                    Ответить
                    • если честно, бустом на работе я пользуюсь давно и плотно
                      но optional не то чтобы был нужен настолько, что без него не писалось
                      вот сейчас сделал греп по всей папке work - найдено 0
                      просто личное мнение
                      Ответить
                      • Ну вообще я имел ввиду std::none как std::default
                        std::string a=std::default; Так вызывается конструктор по умолчанию. Полезно в функциях с дефолт-параметрами. См ниже.
                        Ответить
                        • я ничего не понял
                          мне кажется, оно должно работать только при наличии конструктора от boost::none_t

                          вот это должно компилироваться? (взято по мотивам поста ниже)
                          http://liveworkspace.org/code/c02f8284daaa99860074080d8513236f
                          Ответить
                          • >мне кажется, оно должно работать только при наличии конструктора от boost::none_t
                            Да, именно так. Какой-нибудь тип std::default_t взять и написать во всех классах стандартной библиотеки конструктор от этого типа. Фактически эквивалентно конструктору по умолчанию должно быть. Это позволит юзать параметры по умолчанию в функциях.
                            Например:
                            std::string toString(std::function<std::string(T)> f = std::default)
                            ...
                            toString();
                            Соответственно данный код требует не импликит конструктора в std::function, что принимает в качестве параметра std::default_t.
                            Понятно, что можно юзать std::none и std::none_t, но я не уверен, что это кошерно. Это нарушит пост. Впрочем не мне решать.
                            Ответить
                      • А вот boost::optional штука полезная. Например позволяет в функциях, что иногда не возвращают результат, вернуть отсутствие результата:
                        boost::optional<U> Container::find(const T& id)

                        В результате никаких ошибок связанных с исключениями или с заменяющими их костылями.
                        Ответить
    • я_ничего_не_понял.cpp
      Ответить
      • Заметте, забыли только в строке ::std::stringstream ss;
        В других местах проблем это вызвать никак не может.
        Ответить
    • перед std двойное двоеточие забыли
      Ответить
      • Ну что за день то такой?
        Ещё и не туда ответил:
        http://govnokod.ru/11867#comment155262
        Ответить
        • Вот я уже представляю, как лет через 50 будут заходить в старые топики говнокода и спрашивать: "Посоны, почему ссылка не кликается?"
          Впрочем я как всегда не прав и большая часть слов, из тех что вы видели в цитате выше - уже перестанут употребляться.
          Ответить
          • я бы ещё спросил почему у говнокодов образца 2008го дробные рейтинги
            Ответить
            • Раньше гости могли голосовать за говнокоды и комменты, но только дробным числом, чтобы перевес был только на стороне виртуалов.
              Ответить
    • Я не понял про значение по умолчанию.
      Ответить
    • Блян, когда они уже boost::none в стандарт перетащат?
      std::string toString(std::function<std::string(T)> f = std::none)

      И да, говна, кроме себя, не вижу.
      Ответить
      • Элсо должно быть как-то так:
        toString f value = show $ f value
        toString Nothing value = show value

        show - аналог (std::stringstream()<<value).str()
        Ответить
        • Элсо говна всеже больше, ибо использовали c_str() взамен str()
          Ответить
          • Блян, я слепой. c_str не использовали. Говна всеже поменьше.
            Ответить
            • Элсо, похоже я разговариваю сам с собой, а это клиника. Надо мне самовыпилиться. Этот виртуал уже сошел с ума. Говна в лиспе я все равно почти не нашел. Я начинаю думать, что он божественен, но нафиг почти никому не нужен. Пичалька. Он простой, поэтому обладает системной целостностью.
              Ответить
              • Вы прослушали лекцию проф. ЛиспГовно. Спасибо за внимание.
                Ответить
                • Вы ЛиспГовно прослушали лекцию проф. ЛиспГовно. Спасибо за внимание.
                  fxd
                  Ответить
          • Кстати, интересно, на что указывает возвращённый из функции c_str() и как это удалить из памяти? По идее вообще не должно компилиться.
            Ответить
            • на мусорную память, которая по случайности может всё ещё содержать ту самую строку
              почему не должно компилиться?
              http://ideone.com/mBKfN
              и зачем удалять?
              Ответить
              • > почему не должно компилиться?
                В идеале потому что не будет работать ;)

                > как это удалить из памяти?
                Никак, его уже удалили за вас в деструкторе стд::стринга.
                Ответить
                • Я немного не понял про что вы говорите, но
                  Если написано так: return ss.str().c_str();, то в данной функции никаких проблем не будет, если есть не эксплисит конструктор соответствующий у стринга.
                  >std::string toString(....)
                  Тк toString возращает std::string, то код выше заменится на соответствующий псевдокод:
                  return std::string(ss.str().c_str());
                  Ответить
                  • Если возвращаемый тип std::string - даже в коде в духе return ss.str().c_str() проблем не будет (кроме бесполезного копирования строки в конструкторе std::string(const char*)). Проблемы начнутся если функция возвращает const char *: деструктор строки в момент выхода из функции освободит память, и адрес, возвращенный c_str() будет указывать на освобожденный блок. Самое ужасное - что в некоторых случаях оно даже будет работать до поры до времени.
                    Ответить
                    • static std::string s="";
                      s=ss.str();
                      return s.c_str();
                      Ответить
                      • Скажи "нет" многопоточности. И вообще хватит разговаривать с многопоточностью.

                        Тогда уж так:
                        return strdup(ss.str().c_str());
                        ...
                        // и при вызове
                        const char *s = x.toString();
                        ...
                        free(s);
                        Ответить
                        • Все static переменные в нормальных языках делаются своими для каждого потока.
                          Ответить
                          • D
                            Ответить
                          • Элсо юзай thread_local в крестах
                            Ответить
                            • c++11 ;(

                              Хотя в gcc есть __thread, да и в MSVC тоже должен быть аналог.
                              Ответить
                              • есть, конечно
                                и всегда можно взять
                                http://www.boost.org/doc/libs/1_51_0/doc/html/thread/thread_local_storage.html
                                Ответить
                              • >MSVC тоже должен быть аналог.
                                __declspec( thread ) static
                                Ответить
                          • В нормальных языках внутри метода static переменную вообще не объявить.
                            Ответить
                            • Почему? Как без статиков жить?
                              Ответить
                              • а что они могут сделать, что невозможно без них?
                                Ответить
                                • Ну просто очень удобно в методе сохранять флаги про то, как прошёл предыдущий раз и в зависимости от них делать кой-какие корректировки.
                                  Ответить
                                  • и это вместо того, чтобы в объекте сделать член класса prev_flags
                                    ты ведь понимаешь, что стасик в твоем случае убивает не только приснопамятную многопоточность, но и возможность создать 2 таких объекта?
                                    Ответить
                                    • >и это вместо того, чтобы в объекте сделать член класса prev_flags
                                      А thread_local на члены класса работает?
                                      Ответить
                                      • > А thread_local на члены класса работает?
                                        который c++11?
                                        7.1.1/4
                                        The thread_local specifier indicates that the named entity has thread storage duration (3.7.2). It shall be applied only to the names of variables of namespace or block scope and to the names of static data members.
                                        When thread_local is applied to a variable of block scope the storage-class-specifier static is implied if it does not appear explicitly.

                                        не знаю, как трактовать and - реальной поддержки компиляторами thread_local сейчас нет, нечем проверить
                                        edit видимо, трактовать как "применяется только к тому то и к тому то", так что всё ок. /edit

                                        а так как __declspec(thread) и __thread применяются к статическим членам класса, так что думаю и thread_local тоже будет способен
                                        Ответить
                                    • Понимаю, но хочется, чтобы эта переменная были видна только как можно ближе к месту использования. Да, если её объявить как поле класса и прописать инициализацию в конструкторе, то будет то же самое, но движений придётся делать в разы больше.
                                      Ответить
                                      • > эта переменная были видна только как можно ближе к месту использования
                                        и это говорит крупнейший представитель защиты божественного Паскале-Ада-Дельфишного подхода объявлять все переменные кучей где то на расстоянии пары-тройки пейдж-апов
                                        Ответить
                                        • В Аде переменные объявляй где хошь, учи матчасть.
                                          Ответить
                                          • > В Аде переменные объявляй где хошь, учи матчасть.
                                            не где хошь, а только с помощью declare, начиная новый блок
                                            но лучше, чем в паскале, согласен
                                            технологии уровня с89
                                            Ответить
                                    • Хорошая мысль - static переменые, видимые только в методе, уникальные для каждого объекта (инициализируются в конструкторе).
                                      Ответить
                                      • >>static переменые, уникальные для каждого объекта
                                        Какой же это тогда static? Обычное поле.
                                        PS. В VB вроде такая херь была. Я только один раз, лет 10 назад юзал. А так никогда особо не пользовался.

                                        You can use Static only on local variables. This means the declaration context for a Static variable must be a procedure or a block within a procedure, and it cannot be a source file, namespace, class, structure, or module.

                                        You can use Static only on local variables. This means the declaration context for a Static variable must be a procedure or a block within a procedure, and it cannot be a source file, namespace, class, structure, or module.

                                        http://msdn.microsoft.com/en-us/library/z2cty7t8(v=vs.80).aspx
                                        Ответить
                                      • > static переменые, видимые только в методе, уникальные для каждого объекта (инициализируются в конструкторе)
                                        Так это ж поле... А по видимости только внутри данного метода... а оно надо? Имхо запутает код, спрятав состояние, которое тем не менее будет влиять на работу кода.
                                        Ответить
                                        • Ёбаный хуй, я доказываю крестоблядям полезность фичи, которая есть в крестах и которой нету в Аде. Я троллю сам себя, это апогей пиздеца.
                                          Ответить
                                          • > Ёбаный хуй, я доказываю крестоблядям полезность фичи, которая есть в крестах и которой нету в Аде.

                                            Ну так ведь "TarasB: Я пишу на крестах". После такого троллинг на стороне крестов вполне резонен.
                                            Ответить
                                          • Хе-хе-хе. Повеселил.
                                            Ты осторожней, то скоро превратишься в того, кого годами обсирал.
                                            Ответить
                                          • Тарас КРЕСТОТРАВМИРОВАН
                                            Ответить
                                            • >>Ну так ведь "TarasB: Я пишу на крестах".
                                              Не. Это был наезд на жабу.
                                              Типа жаба настолько уёбищное говно, что я ТарасБ пишу на блядских крестах. Нет, ну вы представляете насколько хуевым должен быть язык, чтобы заставить писать его на C++.
                                              Ответить
                                              • Как и говорит Пи, очень тонко. Определенно это последствия той самой, о которой нам рассказывал Тарас, профессиональной деформации.
                                                Ответить
                                  • переменная-член класса делает всё то же самое, только лучше.
                                    Ответить
                              • > Почему? Как без статиков жить?
                                Зачем без статиков? Со статиками в классах, но не в методах.
                                Ответить
                    • >Проблемы начнутся если функция возвращает const char *
                      Практически то же, что возвращать указатель на эл-т контейнера, который удален.
                      Ответить
                      • > Практически то же, что возвращать указатель на эл-т контейнера, который удален.
                        Ну указатель на эл-т контейнера вообще может сдуться на первой же модификации контейнера. Даже на вставке нового элемента в конец...
                        Ответить
                        • >на первой же модификации контейнера.
                          Предполагающей перераспределение памяти.
                          >Даже на вставке нового элемента в конец...
                          При добавлении в std::list вроде бы не должно.
                          Ответить
                          • В связных списках да, не должно глючить. В векторе, если он не переполнится и не сделает себе resize(), тоже не не поменяется.

                            Но в абстрактном контейнере - лучше перебдеть чем недобдеть ;)
                            Ответить
        • Точнее, так:

          toString (Just f) value = show $ f value
          Ответить
          • Вариант для джедаев:
            toString f = show . (maybe id id f)
            Ответить
            • Ты что-то попутал. Наверное так:
              toString f = show . (maybe id f)
              Ответить
              • А вообще так:
                toString f value = show $ maybe (fromJust value) f value
                Ответить
                • Разве это не сработает?
                  toString (Just f) value = show $ f value
                  toString Nothing value = show value
                  Ответить
                  • Сработает, но это:
                    - Не труъ
                    - Дважды написан show - опять же, не труъ
                    - Никаких суперпозиций. Никакого каррирования. Не труъ.
                    Ответить
                    • >суперпозиций
                      Что ты имеешь ввиду?
                      Ответить
                      • Суперпозиция - применение результата одной функции к другой
                        f . g (x) = f( g( x))
                        Ответить
              • Нет, я не попутал. За подробностями в Hoogle:maybe.

                Если f будет обернут в Maybe, то не так. Если будет унарной функцией, то соберется, но тогда toString будет ожидать вторым аргументом тип Show a => Maybe a, что немного не попадает под изначальную задачу.
                Ответить

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