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

0

  1. 1
++ ++i;

Запостил: 3_dar 3_dar, (Updated )

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

        • Я даже после того, как увидел тот комментарий, захотел написать свой интерпретатор. Сделать ВМ с операторами +, ++, -, --, <, >, <<, >>, [], ввод-вывод как-то обозначить, ввести символ _, который обозначает экземпляр списка команд, копит команды и используется в качестве второго операнда там, где нужен второй операнд.
          class BFMachine {
          public:
            BFMachine& operator + (const CommandList&);
            BFMachine& operator - (const CommandList&);
            BFMachine& operator < (const CommandList&);
            BFMachine& operator > (const CommandList&);
            BFMachine& operator [] (const CommandList&);
            BFMachine& operator | (const CommandList&);
            BFMachine& operator & (const CommandList&);
          private:
            std::vector<char> data;
            size_t pointer;
          };
          
          class CommandList {
          public:
            CommandList operator + (const CommandList&);
            CommandList operator - (const CommandList&);
            CommandList operator < (const CommandList&);
            CommandList operator > (const CommandList&);
            CommandList operator [] (const CommandList&);
            CommandList operator | (const CommandList&);
            CommandList operator & (const CommandList&);
          private:
            std::shared_ptr<CommandList> next;
            Command command;
          } _;
          
          BFMachine vm;
          vm[_-_]>_[_-_<_+_>_]<_&_;
          Ответить
          • _ весь вид портит... Может быть попробовать на префиксных операторах?

            Например:
            + и - декремент/инкремент ячейки
            ++ и -- декремент/инкремент указателя
            & и * ввод и вывод
            ~ и ! образуют цикл

            Жалко, что пробелы придётся писать и квадратные скобочки уже не заюзать...
            Ответить
            • При отсутствии лени можно было бы сделать одновременно и то, и другое. Интересно было бы реализовать случай, когда опереции выполняются по порядку слева направо, от префиксных до постфиксных (впрочем, если без круглых скобок и хотя бы с одним постфиксным, легко: встретилась постфиксная - значит префиксные кончились, можно выполнять).
              Ответить
              • А что, в крестах любая херня может быть оператором?
                Ответить
                • В крестах любая херня может оказаться граблями. Например, операторы || и && после перегрузки теряют свою ленивость.
                  Ответить
                  • то есть у них приоритет при перегрузке меняется? а руками его можно задавать как в хаскеле?
                    Ответить
                    • > приоритет
                      Не приоритет, а ленивость. Штатный оператор не считает правый операнд, если левого достаточно для ответа. А у перегруженного всегда вычисляются оба и только потом оператор получает управление.
                      Ответить
                            • Поэтому inkanus-gray и выглядит таким умным. Он всё же запомнил десять интересных фактов и теперь постоянно пишет их в случайном порядке время от времени как только мы их забудем.
                              Ответить
                        • почему же херота? Всё логично. Перегруженный && может возвращать хоть спутник с орбиты, и ему вполне могут требоваться оба аргумента
                          Ответить
                            • Если женщина страшная, то нужно ли тебе знать про её навык готовки богатый внутренний мир?
                              Ответить
                            • пример (такое поведение явно указано в стандарте):
                              int *i = nullptr;
                              if (i && *i==0) return;

                              Указатель не разыменовывается, потому что && не будет считать второй аргумент если первый false
                              Ответить
                              • Спасибо, капитан, но если второго аргумента нет код тупо не скомпилится. && требует два аргумента, но не всегда использует оба
                                Ответить
                                • ну я это и имел в виду под "требованием". Ведь оператор даже не считает второй аргумент (в отличие от обычной функции)
                                  Ответить
                      • В С++17 туда могут таки вставить точку следования, что полностью пофиксит перегрузку запятой и часть проблем с перегрузками логических операторов.

                        И я где-то видел предложение, если корутины добавят, в лучших традициях многозначности ключевых слов юзать await в перегрузках операторов для ленивого вычисления операндов.
                        Ответить
                      • а теперь вопрос на миллион: если я определяю operator&& как this->someBoolFunc() && other.someBoolFunc(), ленивость поменяется?
                        Ответить
                        • Да. Потому перегруженный оператор - это функция, принимающая два параметра, котоые надо вычислить.
                          Ответить
                  • >Например, операторы || и && после перегрузки теряют свою ленивость.
                    ffffffuuuu~

                    Я всегда знал что перегрузка (синтаксический сахар над вызовами методов) опасна.
                    Годный камень в огород крестоблядей.
                    Ответить
                    • Ну, один из краеугольных камней перегрузки операторов в С++ это "Нехуй перегружать логические операторы, запятую и взятие адреса"

                      А камни кидать погоди, пока точку не разрешат перегружать. Вот тогда можно оторваться.
                      Ответить
                      • В перегрузке логических операторов то какие проблемы? Ты всё равно перегружаешь их для собственных, а не встроенных типов... Или перегружаешь операторы преобразования типов
                        Ответить
                        • А какие проблемы с запятой? Всё те же: отсутствие точки следования, отсутствие ленивости.

                          Кстати в С++ и method chaining не всегда рекомендуется использовать, так как можно нарваться на UB. Поэтому одно из достаточно популярных предложений — добавить точки следования в перегрузки некоторых операторов и между вызовами методов.
                          Ответить
                      • один из краеугольных камней любой фичи в С++ это
                        "мы сделали новую модную фичу Х*"
                        * нехуй пользоваться фичей Х когда Венера с Луной в разных фазах. мы вас предупреждали
                        Ответить
                        • А может дело не в C++, может дело в фичах?
                          Яркие примеры - GC и риалтайм, неявные касты и нетривиальные выражения, рекурсия и переполнение, ленивость и императивный подход.
                          Выходит, надо редуцировать набор фич до тех пор, пока их и вовсе не станет. Что на эту тему говорит Ваш внутренний Дзенский?
                          Ответить
                        • ну, как минимум это лучше, чем
                          "мы добавили новое модное расширение к языку*"
                          *но даже авторы не знают всех его подводных камней
                          Ответить
                • > любая херня может быть оператором
                  g: c++ user-defined literals
                  Ответить
  • Самое главное, что это именно C++. В сишке не конпелируется.
    Ответить
    • 6.5.3.1/2: The expression ++E is equivalent to (E+=1).
      6.5.16/4: If an attempt is made to modify the result of an assignment operator or to access it after the next sequence point, the behavior is undefined.

      Хе-хе.
      Ответить
      • Хахаха, борманд, не говори что это УБ.
        Какая разница что первым выполнится, ++i, или ++i.
        Ответить
        • "Хорошо смеётся тот, кто смеётся последним", - подумал компилятор, и вставил в код rm -rf.

          З.Ы. Он же, вроде как, имеет право сначала взять значение i на вход всех инкрементов, потом сделать все инкременты, а потом сложить их результаты в i...
          Ответить
                • Про 2 присваивания в одну переменную в одном выражении - всех. Просто не надо так делать. Тогда не придётся разбираться во всех этих тонкостях с сиквенс поинтами...
                  Ответить
        • получится

          (a+=1)+=1

          и на втором присвоении сишка тебя нахуй пошлет потому что левая честь не пременная

          а вообще должно развернуться в

          (a = a + 1) = (a = a + 1) + 1

          а тут уже UB


          Борманд, моргни если я прав
          Ответить
          • > сишка тебя нахуй пошлет
            Да. А вот у крестов там почему-то lvalue решили сделать.

            Имхо, лучший вариант в питоне - операторы присваивания не возвращают результатов.
            Ответить
            • Только для простых типов или для перегруженных операторов тоже?
              Ответить
            • но тогда нельзя писать царский код в одну строку...
              Ответить
      • Бля, не в той pdf'ке читал... Это из сишного стандарта было. И там строчкой выше - результат присваивания не является lvalue.

        Плюсы: require a modifiable lvalue as their left operand and return an lvalue with the type and value of the left operand after the assignment has taken place.
        Ответить
        • В общем при присваивании сишка возвращает содержимое, а плюсы - переменную
          Ответить
          • По-моему UB. Т.к. три присваивания в одну переменную без сиквенс поинта между ними.

            Хотя... after the assignment has taken place...

            Хуй знает, короче. Я бы не стал рисковать.
            Ответить
            • по идее
              ++++1
              эквивалентно
              (a = a + 1) = (a = a + 1) + 1

              а тут уже UB ибо может оказаться, что а увеличится на 3
              Ответить
              • Ну да. В стандарте написано, что a += b эквивалентно a = a + b, просто выражение a вычисляется только один раз.
                Ответить
            • как раз из-за того, что ++ возвращает референс на измененную переменную, ub быть не должно. По факту, ++++i это ++(++i), где (++i) вернет &i только после того как i увеличится.
              Ответить

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

Помни, guest, за тобой могут следить!

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


    8