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

    +5

    1. 1
    ++ ++i;

    Запостил: 3_dar, 23 Апреля 2016

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

    • ++++++i;
      Ответить
      • char i = 'H';
        std::cout << i;
        std::cout << ------i;
        std::cout << ++++++++++++++i;
        std::cout << i;
        std::cout << ++++++i;


        http://ideone.com/Dz4HTS
        Ответить
        • да этож брейнфак
          Ответить
          • Я даже после того, как увидел тот комментарий, захотел написать свой интерпретатор. Сделать ВМ с операторами +, ++, -, --, <, >, <<, >>, [], ввод-вывод как-то обозначить, ввести символ _, который обозначает экземпляр списка команд, копит команды и используется в качестве второго операнда там, где нужен второй операнд.
            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[_-_]>_[_-_<_+_>_]<_&_;
            Ответить
            • _ весь вид портит... Может быть попробовать на префиксных операторах?

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

              Жалко, что пробелы придётся писать и квадратные скобочки уже не заюзать...
              Ответить
              • При отсутствии лени можно было бы сделать одновременно и то, и другое. Интересно было бы реализовать случай, когда опереции выполняются по порядку слева направо, от префиксных до постфиксных (впрочем, если без круглых скобок и хотя бы с одним постфиксным, легко: встретилась постфиксная - значит префиксные кончились, можно выполнять).
                Ответить
            • ну раз пошла такая пьянка я банальность напишу

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

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

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

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

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

                            Кстати в С++ и method chaining не всегда рекомендуется использовать, так как можно нарваться на UB. Поэтому одно из достаточно популярных предложений — добавить точки следования в перегрузки некоторых операторов и между вызовами методов.
                            Ответить
                            • перегруженная запятая в некоторых контекстах не вызовется.

                              Где в method chaining может быть UB? Референс на вызывающий объект вернется только после выполнения функции
                              Ответить
                              • В аргументах.

                                s.replace(s.find("xxx"), 3, "yy").replace(s.find("zz"), 2, "aaa");

                                Не отработает как надо

                                Вот собственно бумага: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0145r1.pdf
                                Ответить
                        • один из краеугольных камней любой фичи в С++ это
                          "мы сделали новую модную фичу Х*"
                          * нехуй пользоваться фичей Х когда Венера с Луной в разных фазах. мы вас предупреждали
                          Ответить
                          • А может дело не в C++, может дело в фичах?
                            Яркие примеры - GC и риалтайм, неявные касты и нетривиальные выражения, рекурсия и переполнение, ленивость и императивный подход.
                            Выходит, надо редуцировать набор фич до тех пор, пока их и вовсе не станет. Что на эту тему говорит Ваш внутренний Дзенский?
                            Ответить
                          • ну, как минимум это лучше, чем
                            "мы добавили новое модное расширение к языку*"
                            *но даже авторы не знают всех его подводных камней
                            Ответить
                  • > любая херня может быть оператором
                    g: c++ user-defined literals
                    Ответить
      • > ++ ++i;
        > ++++++i;
        Одно слово: кресты.
        Пойди себя и прибей.
        Ответить
    • Самое главное, что это именно 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...
            Ответить
            • Вот такой код - UB?

              (a *= 7) %= 2;
              Ответить
              • Конечно. Как и x = (a*=7) + (a%=2).
                Ответить
                • Так это только С касается, или С++ тоже?
                  Ответить
                  • Про 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.
          Ответить
          • В общем при присваивании сишка возвращает содержимое, а плюсы - переменную
            Ответить
          • То есть ++++++i в плюсах - это ок?
            Ответить
            • По-моему 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 увеличится.
                Ответить
        • прогнал.
          Ответить

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