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

0

  1. 1
  2. 2
  3. 3
int i = 42;
foo(i); //не компилируется
foo(static_cast<int>(i)); //компилируется

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

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

    • У меня всё компилируется, попробуй другой конпелятор.

      У int переопределён каст в инт?
      Ответить
      • Например так:

        #include <iostream>
        
        typedef int int_t;
        
        class T {
            public:   
                T (int_t i) {
                    this->val = i;
                }
            
                T () {
                    this->val = 0;
                }
            
                explicit operator int_t() {
                    return val;
                }
            private:
                int_t val;
        };
        
        void f(int) {
            std::cout << "kokoko 8:^3";
        }
        
        int main() { 
            #define int T
            int i = 42;
            //f(i); не ко-ко-ко конпелируется
            f(static_cast<int_t>(i));
        }
        Ответить
  • > угадайте, когда такое может быть (С++)
    #define static_cast some_shit
    Ответить
    • Например так
      struct shit{int crap;};
      
      template<typename T>
      struct shit some_shit(T s)
      {
        return {s};
      }
      
      void foo(struct shit a)
      {
      }
      
      #define static_cast some_shit
      
      int main()
      {
        int i = 42;
        foo(i); //не компилируется
        foo(static_cast<int>(i)); //компилируется
      }
      Ответить
    • :)) слушай, ну если бы шутка была про дефайн, то я бы её сюда не принес. Понятно, что надефайнить можно всяго
      Ответить
  • void foo(unsigned x) { ... }
    void foo(float x) { ... }
    К примеру.


    А тьфу, ты же в инт и кастишь.
    Ответить
  • А всё, очень простой ответ же:
    void foo(int&& x);
    i это lvalue, оно в rvalue ref не пролезает. А результат статик каста -- временная хуйня, которая пролезает.
    Ответить
    • и-мен-но!

      можно привести и обратный пример убрав одну &.

      И наконец анекдот
      #include <iostream>
      
      void foo(int&& a) {
              std::cout << "int\n";
      }
      
      void foo(float&& a) {
              std::cout << "float\n";
      }
      
      int main() {
              int i = 1;
              float f = 1.0f;
              foo(i);
              foo(f);
      }


      понятно да, что выведет?)
      Ответить
                • Ну оно в некоторых очевидно косячных кейсах предупреждения выдаёт, и на том спасибо.
                  Ответить
                  • почему gcc не выдает ворнинг тут

                    #include <iostream>
                    
                    void foo(int a) {
                            std::cout << a << std::endl;
                    }
                    
                    int main() {
                            foo(3.14f);
                    }
                    Ответить
                    • А хер их знает... В этом случае хотя бы clang ругается. Но с переменной уже всем пофиг.
                      Ответить
                      • Нужно использовать всякую питушню для статического анализа кода. Я думал, что пишу без ворнингов, а потом включил статический анализатор и охуел: оказывается, я всё это время говнокодил )))
                        Ответить
              • Есть питушня «= delete», вроде бы (!!!) с её помощью можно писать функции типа...

                void koko(int);
                void koko(short) = delete;
                void koko(char) = delete;
                void koko(double) = delete;
                void koko(float) = delete;


                И не будет неявного преобразования.
                Ответить
                • Будет. Если нет других вариантов (хоть удали хоть просто не пиши) -- значит будет.

                  Ок, и правда работает.
                  Ответить
                  • я сам охуел

                    #include <iostream>
                    
                    void foo(int a) {
                            std::cout << a << std::endl;
                    }
                    
                    //void foo(float a) = delete;
                    
                    int main() {
                            foo(3.14f);
                    }

                    скомпилируй
                    а потом раскоментируй строчку
                    Ответить
                    • Всё, дошло. delete не удаляет перегрузку. Он её создаёт и помечает как запрещённую. Она даже засчитывается как ambigious если ты дабл передашь.
                      Ответить
                      • понятно) я как раз думал, что он удаляет неявно созданные методы.

                        По вумному конечно надо было назвать не delete, а deny, но это же С++

                        всё таки я за С++
                        и за Perl
                        и немного за Ruby

                        программирование должно быть нескучным
                        Ответить
                        • template <typename T>
                          void foo(T x) {
                              static_assert(std::is_same<T, int>::value, "foo supports only ints");
                          }
                          Ответить
                      • А ещё можно подключить шоблон, если нужно сразу много каких-то перегрузок запретить. Смотри какая красота:

                        template <typename T> void function(int, T) = delete;


                        Кресты уже почти как тайпскрипт!
                        Ответить
                          • Можно и без int, наверное, я долго не разбирался – просто скопировал код со SO.
                            Ответить
                            • >я долго не разбирался – просто скопировал код со SO.

                              всегда так делаю
                              Ответить
                  • Переписал по-удобному, проверь:

                    void f (int x) {
                        return;
                    }
                    
                    template<typename T>
                    void f (T t) = delete;
                    Ответить
                • Нужна питушня вроде
                  void koko(strict int)
                  Ответить
      • У меня в Си этой хуйни с && нет, именно поэтому я за Си.
        Ответить
        • Для int'овой переменной перегрузка с int&& не катит т.к. переменная lvalue, а && хочет rvalue (значение или временный объект). Тогда конпелятор пробует перегрузку с float&&. Срабатывает неявный каст int во float, а его результат -- временный объект, который является rvalue.

          Ну и для float потом точно так же.
          Ответить
          • Это я понял, но почему не происходит каста int в int&&, а float в float&&?
            Ответить
            • Потому что && ссылки были специально придуманы для случаев, когда ты не хочешь чтобы в них случайно пролезали переменные, которые тебе ещё могут понадобиться.

              Большинство функций, которые принимают &&, это какие-нибудь мув-конструкторы, которые портят аргумент. Поэтому неявного каста из lvalue (переменной) в && нет.
              Ответить
              • А, понял, если скастить int в int&& в foo получится по сути дела lvalue ссылка, отчего теряется смысл &&, а при неявном касте инта во флоат придётся создать временный объект, который как раз и будет будет rvalue?

                #include <iostream>
                
                void foo(int&& a) {
                    a = 5;
                }
                
                
                int main() {
                    int i = 1;
                    float f = 3.14;
                    foo((int&&)i);
                    std::cout << i << std::endl;
                    foo(f);
                    std::cout << f << std::endl;
                }
                Ответить
                  • foo(std::move(i)), лол. Ну или явный каст в &&, что то же самое, но с более общей сёмантикой.
                    Ответить
                      • А, ну временную копию отдай на растерзание.

                        foo(int(i)) например. Или какую-нибудь временную локалку мувни.
                        Ответить
                          • Ну это нормальный паттерн для передачи владения, вай нот?
                            Ответить
                          • если мувнуть шаред птр, то счетчик в итоге останется точно таким же. Старый шарик уже не будет владеть объектом, а новый будет.

                            Шарик в том числе и тем прекрасен, что можно не двигать сам объект. Объект лежит себе в куче, и в ус не дует.
                            Ответить
    • У него же наоборот lvalue не компилируется, а rvalue - да. Или я не понял?
      Ответить
      • почему ты обомне в третьем лице?
        я тут ващето

        foo(i); //не компилируется птому что i (lvalue) не кастится имплистно в rvalue reference
        //без мува
        foo(static_cast<int>(i)); //компилируется бо временная хуйня кастица, она и так rvalue
        Ответить
  • Кстати, а чо компилятор C++ даёт скомпилировать методы, у которых указано возвращаемое значение, но при этом ничего не возвращается?
    Ответить
    • думаю (но не уверен) для совместимости с древним "си", где тип можно было не указывать, и подразумевался int.

      вон брмнд подсказывает
      :~$ c++ -Wall 1.cpp
      1.cpp: In function ‘int foo(int)’:
      1.cpp:5:1: warning: no return statement in function returning non-void [-Wreturn-type]
      }
      Ответить
      • Да не, тут причина очень простая -- есть куча кода в котором никто не заморачивался с фейковым возвратом в недостижимых ветках. Поэтому только предупреждение.
        Ответить
          • > выглядит как говно

            Именно поэтому свежий код полагается писать с максимальным уровнем предупреждений.
            Ответить
              • Незнание законов не освобождает от ответственности.

                Это как писать на perl без use strict, а потом ругаться, что он любой мусор исполняет.
                Ответить
                • Штош, пойду включать ворнинги, ворнинги сами себя не включат
                  Ответить
                • в перле еще нужно
                  use warnings FATAL => 'all';

                  в JS тоже нужно "use strict";
                  а в TS --strict

                  много где нужно
                  Ответить
          • сложно обидеть крестовика назвав кресты говном, крестовик и сам так думает
            Ответить
          • Ну кстати вот банальный пример:
            void foo(int x) {
                if (x >= 0)
                    return 1;
                else
                    return -1;
            
                // здесь return не нужен т.к. эта точка недостижима
                // но конпелятор не всегда может это доказать
            }
            Ответить
              • Нет. Коммент не про ветку с -1, а про недостижимую ветку где функция закончилась.

                В этом случае очевидно, что управление туда не попадёт и третий return не нужен. Но в более сложном случае с циклами и т.п. конпелятор часто тупит и просит написать.
                Ответить
            • Можно экзепшон кинуть, вдруг у пользователя совсем уж куриный проц, в котором неправильно реализованы JGE, JLE, etc...
              Ответить
              • Ага, а потом тебе конпелятор скажет "код недостижим". Особенно забавно, когда у разных конпеляторов разные мнения по этому поводу.

                Хотя и с одним случается... Тарас, помнится, тут что-то такое про паскаль постил.

                Пишешь return -- "код недостижим". Убираешь return -- "не хватает ретурна". И ебись как хочешь.
                Ответить
                • в жабах и котлинах иногда приходица псать типа

                  throw new AssertionError("Can't be")

                  или
                  error() в случ коко
                  Ответить
                  • Везёт вам, что один конпелятор.

                    Или в этих языках "код недостижим" в прицнипе нету?
                    Ответить
                      • У одновозвратников нету, у них один return в конце функции и он всегда достижим.
                        Ответить
                          • Есть языки, где последняя питушня - это return. Можно запретить в кодстайле писать «return» и получить желаемый эффект.
                            Ответить
                            • Хотя нет, пизжу
                              foo = function(x) {
                                if (x > 0) {
                                  5
                                  7
                                } else {
                                  6
                                }
                              }
                              Ответить
                            • > запретить в кодстайле
                              - любой запрет, невозможный с технической точки зрения, есть трата времени
                              Ответить
                              • Проще перейти на питон, где в конце функции просто возвращается None.
                                Ответить
                                    • бросить программирование, купить гитару и выступать по ресторанам, как Золотой Хуй
                                      Ответить
                              • Ещё многие функциональные, конкатенативные япы, если не все.
                                Ответить
                          • Поэтому я за `логическое программирование'. Там недостижимых веток нет.
                            Ответить
                              • Я скорее про Curry думал (это гибрид пролога и хаскеля, если кто не в курсе). Там функции реально могут возвращать значения отовсюду одновременно.
                                Ответить
                                • а в коке тоже есть ошмётки логического программирования?
                                  Ответить
                                  • Да/Нет/смотря где/смотря как понимать. Coq это всё-таки пакет из нескольких языков.
                                    В Gallina логического программирования в традиционном смысле нет (т.е. как в прологе), но с другой стороны, этот язык построен на конструктивистской логике по заветам тов. Martin-Löf.
                                    В Ltac есть некое подобие логического программирования в традиционном смысле, там есть pattern-matching c бэктрекингом. (Ltac — это уровень метушни для Gallina.)
                                    Ответить
                                    • А бывают языки построенные на деструктивистской логике?
                                      Ответить
                                    • единственные реальные системы, использующие логическое программирование, про которые я слышал, это, кстати, какие-то там системы управления умными домами на основе Visual Prolog
                                      Ответить
                                  • foo a | a > 1 = 1 -- При a = 2 эта ветка выполняется
                                          | a > 0 = 2 -- И эта тоже
                                    
                                    > foo 2
                                    1
                                    2
                                    Ответить
                                      • Тогда функция ничего не вернёт, наверное. И эта, кхм, ветка исполнения отбросится.
                                        Ответить
                                        • Заранее неизвестно же, что там отбросится. Следовательно, компилятор никаких warning'ов выдавать не должен.
                                          Ответить
                                          • > Заранее неизвестно же, что там отбросится.

                                            А вдруг он наинлайнил и узнал?
                                            Ответить
                                      • > зачем это надо?

                                        Чтобы не прикручивать костыли в духе linq и не писать перебор вручную.
                                        Ответить
                                          • для того чтобы уйти от энумерации и получить декларативный язык

                                            разница примерно как между тем чтобы в css написать селектор и тем чтобы жсом ходить по нодам и добавлять и убирать стили
                                            Ответить
                                      • Судя по печальному состоянию компиляторов Curry, это не особо нужно. Олег тупо на монадках и продолжениях нечто подобное запилил.
                                        Ответить
                          • В поцкале вообще ретурна нет. Есть exit, но это немного не то. И Дейкстра его обосрал.
                            Ответить
                            • Точно, Паскаль же умеет в несколько возвращаемых значений.

                              Именно поэтому я за
                              Ответить
                            • В паскале возвращать значение мжет только функция (а не процедура) и вроде как завершение там описывается как

                              funcName := result

                              нет?
                              Ответить
                              • > funcName := result

                                Да. Но выглядит как ёбаный костыль, как-будто процедуре прикрутили невидимый аргумент по ссылке. А всё ради одновозвратности.
                                Ответить
                              • Это не завершение, а запись результата.

                                Завершается функция либо дойдя до конца, либо по exit.
                                Ответить
                    • >Или в этих языках "код недостижим" в прицнипе нету?
                      есть, но в очень простых случаях

                      if (true) {
                      return;
                      }
                      int a = 1; //скорее всего может не скомпилирвоаться
                      Ответить
      • Включился ворнинг: "говно забыло уходить". Гет аут фром хире!
        Ответить

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

Где здесь C++, guest?!

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


    8