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

    −43

    1. 1
    bool ok = (state == 0) ? false : true;

    И это пишет человек, пишущий на плюсах уже много лет...

    Запостил: glook, 05 Июня 2012

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

    • Ну сколько можно постить эти бульшиты... Скучно же.
      Ответить
      • Никак не привыкну к таким вещам. Передёргивает.
        Ответить
    • Заебло.
      Ответить
    • bool ok=state, всё
      Ответить
    • http://liveworkspace.org/code/ebcdda06e3723bbc31ad50a43e904d17 А если такой вариант?) Не видно же чем является state в данном коде.
      Ответить
      • bool ok = state некорректно, лучше написать bool ok = state != 0. А оно заработает и на вашем примере.
        Ответить
      • А вообще за вашу реализацию оператора ==, сравнивающую bool и int надо убивать.
        Ответить
        • Дык я же не говорил, что это хорошо.
          ЗЫ ok = state != 0 не заработает без перегрузки соответствующего оператора.
          http://liveworkspace.org/code/47a683ac91ec0b441cbd6ce3b0e2ea35
          Ответить
          • Но перегружать == и не перегружать != это, опять же, моветон.
            Так что будем считать, что != перегружено.
            Ответить
    • Think C++ way
      bool ok = static_cast<bool>(state);
      :)
      Ответить
      • А bool ok = state == 0 вам чем не угодил?
        Ответить
        • Это недостаточно по-крестоблядски.
          Ответить
        • Think С++ way. ;)

          Код читается по-разному:
          i) bool ok = state == 0; => положи в ok флаг соответствия state состоянию int 0
          ii) bool ok = static_cast<bool>(state); => положи в ok битовое соответствие state.
          Ответить
          • Ага, положишь ты побитово туда число 2, а потом удивляться будешь, какого хуя ^ от двух ПРАВД даёт тоже ПРАВДУ.
            Ответить
            • Тарас! Как всегда...
              Скажешь какую-нибудь ерунду не по делу :)
              Ответить
              • Не, серьёзно, из-за фигни в буле ксор от двух правд бывает правдой, а это пиздец логике.
                Ответить
                • Не, каст в бул загонит его в корректный для булов диапазон.
                  http://ideone.com/SCWMZ
                  Ответить
                • Ммм... Программист же должен знать какие state правда, какие ложь и заполнять булевкий бит соответственно.
                  Ответить
          • Ага, и причем вариант i) имеет смысл всегда, а ii) только в редких случаях, когда физическое представление була совпадает с представлением состояния :)

            Это не с++ way а какое-то байтоебство.
            Ответить
            • Ммм.... Не понял, какое такое физическое представление була должно совпадать с каким таким представлением состояния?
              Ответить
              • Ну вот в этом конкретном случае у нас state==0 это успех, а state!=0 это фейл, только поэтому static_cast тут и работает. А если успех обозначен как state==42? Или какой-нибудь ESUCCESS или Status::Success?

                Так вот к чему я клоню - зачем применять каст там где он сроду не нужен, и можно написать простое, универсальное и понятное всем state == 0?
                Ответить
                • class State {
                  private:
                  int INTSTATE;
                  SomeEnumState ENUMSTATE;
                  public:
                  bool() {
                  return INTSTATE == 42 || ENUMSTATE == ESUCCESS;
                  }
                  };
                  Ответить
                  • И где тут ваш статик каст ? )
                    Ответить
                    • Эээ... bool()?
                      Ответить
                      • State state;
                        bool b = state;

                        Поскольку bool() не explicit - все будет работать. Если же у нас с++11 и оператор explicit - то да, нужен каст. Но в таких случаях, имхо, лучше isSuccess(). Короче чем каст, и лучше показывает намерения.
                        Ответить
      • bool ok = !!state;
        Ответить
        • Тьфу, ну вот обязательно надо запутать все к хуям ;) А если удачный статус это 42 или ESUCCESS?
          Ответить
          • >обязательно надо запутать все к хуям

            Конечно, http://ideone.com/HLLIH
            Ответить
      • Think real C++ way
        bool ok = state;

        state - конечно же, объект, в котором есть operator bool () (на крайний говнослучай, не будем показывать пальцем - operator void *())
        Ответить
        • Это не С++ way. Это C way.

          С++ way: double b = static_cast<double>(3)/static_cast<double>(2);
          Ответить
          • поясжните мысжль
            Ответить
            • Должно правильно читаться.

              У вас написано: положи в ok state o.O причём они разных типов... Fail!
              Ответить
              • положи в bool ok значение, которое объектом state предусмотрено отдаваться как bool. Success! Profit!

                да, мсье ведь в курсе, что в с++ все три приведения типов эквивалентны:
                int a = 100;
                bool b = a;
                bool c = (bool)a;
                bool d = static_cast<bool>(a);
                Ответить
                • Нет. Этого здесь не написано.
                  Вот если bool ok = static_cast<bool>(state); То да, как раз так. Специально и придумали эти штуки, чтобы читать можно было, а не домысливать из "вселенского разума". Это ж один из немногих профитов C++.
                  Ответить
                  • здесь это как раз написано
                    bool x = z;
                    z приводится к типу bool
                    да, именно с помощью static_cast приводится к bool неявно
                    да, c-cast, записанный как (bool), для целочисленных типов будет приводиться компилятором как static_cast
                    Ответить
                    • Перец ясен, что будет неявно. Неявно -- это и есть "домыслить". C way. No way! Do Static_cast be a good boy!
                      Ответить
                      • что, какие то проблемы по приведению int к bool, не хватает регистровой памяти запомнить простые правила?
                        опять искалеченные паскалем судьбы в православных разделах на гк??
                        Ответить
                        • Кофе теперь бывает и оно. Но приличные мальчики пьют чёрный.
                          Ответить
                          • c++03 standard
                            4.12/1
                            [conv.bool] 4.12 Boolean conversions
                            An rvalue of arithmetic, enumeration, pointer, or pointer to member type can be converted to an rvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true.

                            очень запутанные вещи написаны в стандарте, очень
                            Ответить
                            • Эти правила не относятся к тому, как прилично оформлять код.

                              Когда в коде становится много всяких подобных abandon слов, приходится дочитывать то, что не написано. Это хорошо в художественной литературе, а не в коде.

                              Кто экономит на чистоте: тот или вор, или свинья. ;)
                              Ответить
                        • Ах, да. И конечно это всё только потому, что у меня парень далеко, а я скучаю. :(
                          Ответить
                      • Если неявный каст имеет простую и понятную семантику - то почему нет?
                        Ответить
                        • Вообще говоря, это делается для сообщения явно определённой информации.
                          Я хочу создать один объект из другого и я точно знаю что, я уверен, что это возможно разрешить на стадии компиляции... И прочее бла, бла, бла.

                          Когда вы хотите что-то спросить у человека, вы подходите и заявляете: "Скажи-ка дядя, ты не видал здесь такого... с пупочкой?" или "Милостивый государь, не соблаговолите ли вы <...>"

                          Вот и разница между неявным и явным кастом.
                          Ответить
                          • Все зависит от того что и во что мы кастуем.

                            Вы же не кастуете явно указатель на дочерний класс в указатель на родительский?

                            Или int в double в выражениях?

                            Так что неявный каст это не абсолютное зло.
                            Ответить
                            • Ну... Так никто не говорит, что это зло. :)
                              Но не C++ way ;)
                              Неявный каст это из C. C++ более вежливый язык.

                              bool ok = state; Где здесь C++? :)
                              А вот где: bool ok = static_cast<bool>(state); :D
                              Ответить
                  • Чтобы читать и не домысливать придумали методы is*().

                    Если назначение оператора bool() очевидно - то каст не нужен, он понятности не добавит.
                    Если же назначение оператора bool() не очевидно - то такой оператор не нужен. И каст тоже.
                    Ответить
                    • вообще весь топик вырос изначально из инвалидности микрософтовского компилятора
                      это у него на /W3 на пустом месте вырастает ворнинг C4800: 'type' : forcing value to bool 'true' or 'false' (performance warning), в котором они официально заявляют, что все три указанных мной преобразования не спасут: уou can add "!=0" to the expression, which gives the expression type bool. Casting the expression to type bool will not disable the warning, which is by design.
                      Ответить
                      • Ну не знаю, не люблю я каст int в bool. Просто не вижу в этом конкретном касте смысла. Непонятно только почему у MS это performance warning. Неужели этот каст компилируется во что-то сложнее state!=0?
                        Ответить
                        • ни во что хитрожопое он не компилируется, всё стандартно
                          просто ворнинг они не хотят убирать by design, вот и все
                          обычное дело для microsoft с ихними wontfix
                          int main()
                          {
                          01151000  push        ebp  
                          01151001  mov         ebp,esp  
                          01151003  sub         esp,8  
                          	int a = 100;
                          01151006  mov         dword ptr [a],64h  
                          	bool b = a;
                          0115100D  cmp         dword ptr [a],0  
                          01151011  setne       al  
                          01151014  mov         byte ptr [b],al  
                          	bool c = (bool)a;
                          01151017  cmp         dword ptr [a],0  
                          0115101B  setne       cl  
                          0115101E  mov         byte ptr [c],cl  
                          	bool d = static_cast<bool>(a);
                          01151021  cmp         dword ptr [a],0  
                          01151025  setne       dl  
                          01151028  mov         byte ptr [d],dl
                          Ответить
                    • Это плохим программистам не добавляет. Им уже никакой _cast не добавляет.

                      А про is<Smth>(), конечно верно. static_cast говорит лишь о желании создать один тип из другого.
                      Ответить
                  • >Специально и придумали эти штуки, чтобы читать можно было, а не домысливать из "вселенского разума". Это ж один из немногих профитов C++.
                    Я, может быть, чего-то недопонимаю, но ведь С++ как раз был изначально спроектирован как суперсет С с "вселенским разумом" который для нас behind the scenes реализует все типы и все базовые преобразования между классами (родитель-потомок).

                    Т.е. я понимаю там, надобность введения reinterpret_cast<>, чтобы реализовывать какие-то хаки/общаться со старым кодом. Но вот зачем отдельные static_cast и dynamic_cast, мне не понятно. Возможно я не учитываю какую-то деталь. По-моему, компилятор владеет достаточной информацией, чтобы самому понять, какой тип каста должен быть, а читающему код и так очевидно. С++ сам за меня реализует все VTable и внутреннюю реализацию и много прочей байды (в отличие от С) -- я об этом не должен задумываться. Так почему же С++ заставляет задумываться о "динамичности" каста? Возможно, конечно, тут что-то влияет на производительность интерпретации шаблонов.
                    Ответить
                    • http://ideone.com/Ut567
                      Ответить
                      • Я не о том, как это реализовано сейчас. Я о том, как можно было бы всего этого избежать. Вот допустим, есть старые С-интерфейсы, где, допустим, указатель на функцию в качестве аргумента принимает некий контекст, смысл которого известен только автору, поэтому поставлен void*. Здесь я бы разрешил использовать только reinterpret_cast. Если я не ошибаюсь, С++ разрешает и static_cast. Зачем? Что касается вашего примера, то опять же, мне непонятно, зачем разрешать даункаст в неправильный тип без проверки? Для нарушения правил у нас и так есть reinterpret_cast. И вообще зачем делать даункаст без проверки? Думаю, редко где надо, и в производительности выигрыш сомнительный. Зато народ путается в них и стреляет в себе ногу.
                        Опять же, я могу ошибаться где-то.
                        Ответить
                        • Даункаст без проверки иногда нужен, когда и так 100% по логике не может быть не тот тип.
                          Ответить
                          • Тем не менее это не является поводом вводить в язык лишнюю конструкцию. Если действительно по логике третьего не дано, в теории компилятор должен увидеть это в компайл-тайме. Иначе это игры с огнём. Если же прямо уж так нужна производительность, то не лучше ли писать участок кода прямиком в С-стайле без иерархией, чем в цикле употреблять двадцать три фабрики с тридцатью адаптерами, попеременно кастуя их друг в друга?
                            Ответить
                          • В общем, если бы я был трупом страуса, то я бы сделал так:

                            C-style каст по своему определению (ибо это C-style) -- это reinterpret_cast для указателей, но static_cast для примитивов типа int <--> bool

                            Вместо же dynamic_cast и static_cast ввёл бы один общий cast<> с дополнительным аргументом-флагом: cast<Derived, NO_RUNTIME_CHECK> и cast<Derived> (синоним к cast<Derived, DO_RUNTIME_CHECK>)

                            Возражения?
                            Ответить
                        • > в производительности выигрыш сомнительный
                          очень даже не сомнительный - у меня вышло в 50 раз быстрее
                          http://pastebin.com/49RQKi0w
                          Ответить
                          • Синтетический пример, кому он нужен? Давайте пример из реальной жизни, где это является реальным боттлнеком.
                            Ответить
                            • динамик каст из реальной жизни?
                              существует крайне мало случаев, когда без него не обойтись
                              обычно злоупотребление динамик кастом свидетельствует об архитектурной ошибке

                              а синтетический пример показывает, что 1 динамик каст в 50 раз медленнее 1 такого же статик каста

                              о чем флейм? что все касты заменить на c-style? этого не будет
                              ты в компайл-тайм не сможешь выловить 100% случаев совместимости типов и нахождения в нужном месте в иерархии - даже в линк тайме не сможешь, потому что всегда есть возможность написать dll, о которой никто ничего не знает на этапе компиляции твоего приложения

                              а делать пессимизации и все передачи указателей/ссылок на объекты просеивать через сито динамик-каста - нет нет нет
                              Ответить
                              • Я не говорил, что динамик-каст прямо уж так нужен. Я говорил, зачем разный синтаксис на каждый чих. Не только динамик-каст, но и любой даункаст (в том числе статический) по своей сути является архитектурной ошибкой. Перечитай ещё раз, что я написал, чё-то ты не о том всё.
                                Ответить
                                • ну перечитал
                                  отдельные статик каст и динамик каст - первый приводит типы как считает нужным в компайл-тайме (и только в нем), второй лезет в иерархию классов и пытается там найти ответ в рантайме (быть может какой нибудь оптимизатор найдет в компайл-тайме, но на это рассчитывать нелепо)
                                  при этом первый работает как бы с любыми типами, второй только со ссылками и указателями.
                                  в режиме работы с ссылкой неуспешное приведение dynamic_cast сгенерирует исключение std::bad_cast, с указателями - нулевой указатель
                                  неуспешное приведение static_cast приведет к ошибке компиляции

                                  эти отличия не убеждают?
                                  Ответить
                                  • >эти отличия не убеждают?
                                    Нет, полная каша же, и я нигде так и не увидел оправдания ей. См. http://govnokod.ru/10569#comment144035
                                    Ответить
                                    • причем тут обратная совместимость с С и идеологически разные касты static и dynamic
                                      какое компилятор должен принимать решение, если я напишу (SomeType *)ptr?
                                      в какое время он это обязан делать (компайл тайм, рантайм)? будет ли единство?
                                      Ответить
                                      • >какое компилятор должен принимать решение, если я напишу (SomeType *)ptr?
                                        в какое время он это обязан делать (компайл тайм, рантайм)?
                                        Как я написал выше в коменте, т.к. это С-style, то и кастовать в "идеальном С++" оно должно было бы как С, то есть как reinterpret_cast в общем случае, или как static_cast, если ptr имеет тип void*. То есть компайл-тайм.

                                        Чтобы был райнтайм, в "идеальном С++", который проектировал бы я, использовался бы cast<> с дополнительным флагом по желанию, при котором можно отключить рантайм-проверку типов (для даункаста если хочется супер-производительности).

                                        В остальном это забота компилятора определять, какой тип каста нужен.

                                        Они "идеологически разными" вам кажутся только потому что вы привыкли к ним в С++. На самом деле они redundant и messy.
                                        Ответить
                                        • Один каст,но с флагом. В чём выигрыш?
                                          Два разных даже удобнее: сразу видно о чём речь. А так бы нам ещё во флаги всматриваться, да пытаться понять логику компилятора, где он какой каст вставил. И так тяжело бывает следить за неявным кастом, а по вашей логике ещё и за явным глаз да глаз. Неудобно ужасно. Неуважение к программисту какое-то.

                                          Это всё равно, что команды распараллеливания в OpenMP: зашарашат, а потом думают: "Почему не работает?", а оказывается компилятор подтуповат, не уловил задумку клёвого прогера и "не так" распараллелил.
                                          Компилятор должен быть как можно глупее. Только самое лобовое делать: ать-два, ать-два. Избавлять программиста нужно от необходимости выполнять монотонную работу, копипасты, например.
                                          Ответить
                                          • > Компилятор должен быть как можно глупее. Только самое лобовое делать: ать-два, ать-два.
                                            Есть такой, называется ассемблер.

                                            > Избавлять программиста нужно от необходимости выполнять монотонную работу, копипасты, например.
                                            И в ассемблере как раз есть макросы.
                                            Ответить
                                          • >Один каст,но с флагом. В чём выигрыш?
                                            В том, что для отключения функции, не нужно вводить новый интерфейс. Напр. в D буфер в стеке по умолчанию инициализируется нулями. Если хочешь это отключить (что нужно редко, где-нибудь в цикле пару раз на всю программу) -- пиши "= void" в конце. Если бы D проектировал индус Страуструп, то он бы тут забацал два примитивных типа unsafe_byte_array и safe_byte_array и ещё бы заставлять кастовать между собой через ещё один интерфейс :) И его адепты бы восхваляли "очевидный и простой синтаксис".

                                            >Два разных даже удобнее: сразу видно о чём речь
                                            А зачем тебе нужно это видеть? Прематуре оптимизатион. Вот если окажется, что где-то есть даункаст в очевидный тип, и в этом боттлнек согласно профайлеру -- тогда задумывается и вставляй флаг, отключающий рантайм-проверку. В остальных случаях тип каста должен определяться самим компилятором, а не вручную программистом. Может быть ещё и методы скажете дёргать из VTable'а вручную? В чём тогда пойнт использовать С++, а не С?

                                            >А так бы нам ещё во флаги всматриваться
                                            Т..е., по вашему NO_RUNTIME_CHECK один раз в год -- менее очевидно, чем static_cast с размазанной семантикой?

                                            >Компилятор должен быть как можно глупее
                                            И поэтому нужно писать static_cast<bool>, хотя компилятору и так очевидно, что это статический каст? Тут совсем не нужно компилятор делать суперумным.

                                            >Избавлять программиста нужно от необходимости выполнять монотонную работу
                                            Да, вроде как писать static_cast и dynamic_cast там, где можно было бы написать просто cast (как единый притимив, в целом противопоставляемый С-style-касту).
                                            Ответить
                                            • >А так бы нам ещё во флаги всматриваться
                                              >а по вашей логике ещё и за явным глаз да глаз
                                              NO_RUNTIME_CHECK как раз кричит во весь код, что здесь оптимизация, отключили проверку: может быть креш, если что-то поменяем. При static_cast<WrongDerivedClass*> нихрена это не очевидно.
                                              Ответить
                                              • > который проектировал бы я
                                                > NO_RUNTIME_CHECK
                                                удачи, кастуй очевидные вещи в рантайме, зануляй в стеке буферы по умолчанию
                                                > работа компилятора определять
                                                ну так используй c-cast, в чем проблема, улучшатель
                                                > с размазанной семантикой
                                                > нихрена это не очевидно
                                                если ты чего то не осилил - это твои личные проблемы
                                                учить тебя тут уму разуму никто не собирается
                                                курсы С++ для начинающих - в другом месте
                                                Ответить
                                                • >удачи, кастуй очевидные вещи в рантайме
                                                  Ну если тебе всё и всегда очевидно, то зачем тебе вообще типизация? Используй void*, гений.
                                                  Ответить
                                                  • именно благодаря типизации и широким возможностям по приведению типов в с++ у меня всё отлично работает, это позволяет крайне редко использовать static_cast/reinterpret_cast (ололо, как раз для наложения сишных структур на принятый из сети буфер), и никогда const_cast и dynamic_cast
                                                    а у тебя очевидный батхёрт от такой простой вещи
                                                    я тебе по секрету скажу, что даже static_cast в нормальном приложении должен быть серьезно оправданным случаем
                                                    Ответить
                                                    • >это позволяет крайне редко использовать static_cast/reinterpret_cast
                                                      >и никогда const_cast и dynamic_cast
                                                      Гы. А что же ты тут тогда лопочешь про оверхед в рантайме, если ты их почти не используешь? Типичный premature optimization головного мозга.

                                                      И я ничего не говорил о том, что кастование само по себе это ух как здорово.

                                                      >static_cast/reinterpret_cast
                                                      >ололо, как раз для наложения сишных структур на принятый из сети буфер
                                                      Сенсация: здесь специальный оператор кастования на уровне языка не нужен, обычный уже существующий C-style подойдёт. Не нужно вводить кучу примитивов на каждый чих -- тем более что сишные структуры как раз требует сишного подхода.
                                                      Ответить
                                                      • если для тебя так туго доходит - вместо реального сишного каста, компилятор с++ на синтаксис сишного каста возьмет один из трех своих _cast - это именно то, чего ты просил - "я не хочу разбираться в непонятном наборе _cast, я хочу новое платье!"
                                                        о том, почему один менее безопасный сишный каст превратился в три более безопасных ты почитаешь в открытых источниках
                                                        в этом топике я приводил пример
                                                        Ответить
                                                        • >вместо реального сишного каста, компилятор с++ на синтаксис сишного каста возьмет один из трех своих _cast - это именно то, чего ты просил - "я не хочу разбираться в непонятном наборе _cast, я хочу новое платье!"

                                                          Это до тебя туго доходит. Ты опять говоришь мне о текущей реализации С++, а я говорю о том, как *следовало бы* сделать. Следовало бы reinterpret_cast, static_cast<T*>(void*) и static_cast<int> объединить с C-style-cast (повторяю для тупых -- не так, как оно реализовано сейчас в С++!), противопоставив C++style, class-based cast<>, где можно отключить рантайм-проверку для производительности. Здесь всё прекрасно очевидно, что компилятор вставит. Закрывая дыры Си, _cast-стайлы вводят собственные дыры, так что я не вижу особой причины радоваться.
                                                          Ответить
                                                • >курсы С++ для начинающих - в другом месте
                                                  Ну конечно если ты уже замусорил свою голову этим полупьяным бредом -- то оно тебе очевидно.

                                                  Я же просто говорю про изначально более чистый дизайн (по моему мнению).

                                                  В дизайне ПХП тоже много пьяного бреда, и я уверен, ты бы так же защищал ПХП, выучив все corner cases -- подменяя аргумент о хорошем дизайне аргументом о том, что ты осилил выучить этот дизайн -- следовательно, он хорош. Молодец.
                                                  Ответить
                                            • Не только тип каста не должен определяться компилятором, а даже если вообще компилятор увидел каст, нужно тревогу поднимать, звать полицию и МЧС.
                                              Ответить
                                              • Поддерживаю концепцию "по умолчанию - наиболее безопасное и осторожное поведение, хочешь скорость в ущерб безопасности - вешай прагму".
                                                Ответить
                                            • Так, Вольт, это серьёзно.

                                              Там где люди ставят каст, означает, что компилятор уже не в силах что-нибудь разрешить. Люди в здравом уме такой аншлаг, как static_cast<bool>(int) не пишут. Зачем они нужны трёх типов я уже здесь где-то написал: в какой момент возможно разрешить валидность кастовки.

                                              Вам что сто типов каста нужно, раз вы флаги навешиваете?! Или вы плохо понимаете семантику слов static_ и dynamic_? Какая размазанность?
                                              Заканчиваем балаган. Никакого супер-гавка.
                                              Ответить
                                              • > Заканчиваем балаган.
                                                Крестосрач считаем завершенным?
                                                Ответить
                                                • А ведь ещё const_cast не обмусолили!
                                                  Ответить
                                                  • А что его мусолить. Он опасен и нужен крайне редко. И его использование - скорее всего баг в архитектуре.
                                                    Ответить
                                                    • Давайте его вообще отменим! А чё? Баг в архитектуре?! Сам виноват -- чини!

                                                      Так... Надо писать письмо в комитет по стандартизации, чтобы в новом C++ 2014 к олимпиаде в Сочи const_cast убрали.
                                                      Ответить
                                                      • Я имел в виду что есть 0.1% случаев когда const_cast действительно нужен и его не избежать, и тогда, осознавая все его последствия (а все ли последствия вы осознаете, когда используете const_cast?), и тщательно взвесив их, им можно воспользоваться.

                                                        В остальных 99.9% случаях const_cast юзают или по дурости и неумению пользоваться const'ами или для затыкания дыр во внешних либах, автор которых не осилил const'ы.
                                                        Ответить
                                                        • Думаю, что const_cast используется исключительно для обратной совместимости. Когда новый интерфейс поддерживает константность, а старый нет.

                                                          Сложно себе представить жизненную ситуацию, где внутри совместных интерфейсов может возникнут необходимость нарушить такой важный контракт.

                                                          Сами посудите.
                                                          Константность означает, что поставщик запрещает вам вмешиваться во внутреннюю структуру поставки, потому что это может вызвать нарушение согласованности. Если вы можете снять const, нарушить контракт, и при этом оставить поставщика и поставку в согласованном состоянии, значит либо вы знаете достаточно много о внутреннем устройстве поставщика, либо делаете это небезопасно из-за несогласованности контракта сдачи-приёмки.
                                                          И то, и другое -- это нарушение архитектуры. Нужен адаптер, врепер -- что угодно, что разрешит конфликт контракта, либо у вас нарушена инкапсуляция и нужно пересмотреть разбиение на классы.
                                                          Ответить
                                                          • > Думаю, что const_cast используется исключительно для обратной совместимости.
                                                            Надеюсь, что библиотек, в интерфейсах которых не расставляют const уже не осталось.
                                                            Ответить
                                                            • Ну... Существуют неизменные библиотеки для численного анализа. Все они используют некостантный интерфейс. Чтобы не нагружать и без того сложные вещи ещё и адаптерами, полагаются на const_cast. И так будет ещё много лет, думается.
                                                              Ответить
                                                              • Блин и этот человек рассказывал мне про строгость, и необходимость использования явного static_cast...

                                                                > Существуют неизменные библиотеки для численного анализа.
                                                                У вас есть код этих библиотек? Если есть - садитесь и расставляйте const'ы. Ими вы ничего не испортите - ни самой библиотеки, ни софта который ей пользуется. За пару дней, думаю, управитесь.

                                                                Если кода нет, и из достоверных источников вам известно, что функция не портит аргументов (например так сказано в документации) - смело правьте ашку, дописывая в нее const.

                                                                Если же кода нет, и вы не уверены в том, что эти функции ничего не модифицируют - то какого #$% вы вообще используете const_cast!?
                                                                Ответить
                                                                • Вы чего-то не то сейчас сказали...

                                                                  Гораздо быстрее в своей конкретной программе поставить два каста в нужном месте, где я уверен, что всё будет хорошо.
                                                                  Какой смысл трогать библиотеку и заниматься чпоканием констов в сотне местах и просто тереть пальцы? Тем паче об исходный код, пусть они даже и есть. Я же его не править, а переиспользовать хочу.
                                                                  Ответить
                                                                • Кроме того, это действительно редкие случаи. Крупные библиотеки либо переписаны самими вендорами, либо это совсем новые, созданные уже в эру уважения к константности, скажем так.
                                                                  Ответить
                                                                  • > Кроме того, это действительно редкие случаи.
                                                                    Ну если либа под свободной лицензией, то почему бы не принести пользу сообществу, расставив в ней const'ы? Тогда таких библиотек станет еще меньше ;)

                                                                    > Гораздо быстрее в своей конкретной программе поставить два каста в нужном месте, где я уверен, что всё будет хорошо.
                                                                    Искренне надеюсь, что эта уверенность порождена анализом исходников, а не тестированием.

                                                                    > Чтобы не нагружать и без того сложные вещи ещё и адаптерами
                                                                    > поставить два каста
                                                                    Два wrapper'а сильно усложнят программу?
                                                                    Ответить
                                                                    • Вы хотите принести много пользы? Возьмите исходники NR и везде, где найдёте неизменяемые входные параметры функций, анализируя исходники, расставьте const.

                                                                      Если написано, что данные по такому-то пришедшему указателю не меняются, то можно смело кастовать ссылку на внутренние данные в неконстантную для передачи в функцию.

                                                                      Да, wrapper длиннее каста. Кроме того, каждый "новый" код -- это, собственно, и есть wrapp старого кода, который я переиспользую, в нечто новое.

                                                                      Вы явно потеряли мысль: не исправить, а использовать то, что сделано.
                                                                      Ответить
                                                                      • NR = Numerical Recipes? Оно платное - вот пускай сами и пилят. И неужели в 3rd edition c++ тоже нет констов?

                                                                        Ну если этот код и есть высокоуровневая обертка над NR - пусть будут const_cast'ы ;) Лишь бы в прикладном коде их не было.
                                                                        Ответить
                                                  • [вброс] const_cast - громозок. Не нужен.
                                                    Хочу:
                                                    unconst(a)=b;
                                                    f(unconst(a));
                                                    А ещё окромя static_cast и dynamic_cast хочу agree_cast, например:
                                                    a=agree_cast(b);
                                                    f(agree_cast(b));
                                                    Кстати, unconst(a) я делал на шаблонах, добротно получилось.[/вброс]
                                                    Ответить
                                                    • Должен быть только один kosher_cast!
                                                      Ответить
                                                      • Она, брат, она! Без вариантов.
                                                        Та самая кошка!

                                                        Новый язык программирования:Do.
                                                        Пишешь Do, и компилятор компилирует это в прогамму :)
                                                        Ответить
                                                    • > const_cast - громозок.
                                                      И правильно. В том 0.1% случаев когда он действительно нужен, а не притянут за уши к кривой архитектуре - его можно и написать.
                                                      Ответить
                        • >зачем разрешать даункаст в неправильный тип без проверки?
                          dynamic_cast не всегда работает, поэтому придумали такой костыль.
                          Ответить
                    • С++ НЕ задумывался как надстройка над С. В головах он родился как самостоятельный язык, который бы обладал основными преимуществами ООП, но был бы столь же производительным, как не ООП. "Обратная совместимость" с C -- это уже "рыночный" ход. То есть, захватить многое из С -- снизить порог вхождения программистов C, которых много, в новый язык.

                      Относительно кастов... static_cast -- разрешается на стадии компиляции. dynamic_cast -- разрешается во время исполнения, reinterpret_cast --разрешается никогда. const_cast -- для обхода запрета.
                      Ответить
                      • >С++ НЕ задумывался как надстройка над С
                        Да, и именно поэтому Страуструп при создании назвал его C with Classes. И поэтому ввёл совместимость на уровне исходного кода, хотя мог ввести просто ABI/API совместимость (как в C# сделали), избавив свой гениальный язык с "преимуществами ООП" от кучи кривых хаков, введённых в первую очередь потому, что С++ задумывался именно как суперсет С.
                        Ответить
                        • Нет, это что-то уже позднее, когда сформировалась ясная доктрина решения проблемы.
                          Ответить
                        • Использовать C в качестве основы было решено уже, когда Страуструп работал в Bell Labs. Как-то так. Там даже не о C шла речь, а о каком-то другом языке.
                          Ответить
                          • Если бы Страуструп не хотел делать С++ суперсетом С, то вместо С++ у Страуструпа бы вышло подобие языка D. Так же теоретически производителен (C++ может быть производительнее только потому, что у С++ больший userbase и лучшие tools), синтаксис похож на С, поддерживает линковку С-модулей, но в то же время не тащит за собой целый ворох фигни из С, и тем более не пытается мимикрировать под него. Большинство ловушек в С++ -- это именно как раз следствие того, что хотели мимикрировать некую конструкцию под С, но до конца не получилось, вот и вышла хрень.
                            Ответить
              • У плюсов нестрогая типизация, с бобрым утром.
                Ответить
                • Это у плохих программистов нестрогая типизация в C++. :) С вечером вас.
                  Ответить
                  • Это свойство языка, а не программиста.
                    Ответить
                    • В программисте всё дело, в оформлении кода. Можно оформить так, что всё будет строго, а можно оформить так, что непонятно что, непонятно куда.
                      Это наследие от С.
                      Но у хороших С++ программистов типизация строгая. И они помидоры в огурцы не кладут.
                      Ответить
                      • МЕНЯЮ СТРОГОСТЬ ТИПИЗАЦИИ ЯЗЫКА ПО ФОТОГРАФИИ
                        Ответить
                      • это называется code bloat
                        если сущность из коробки предоставляет operator bool, нелепо везде писать static_cast<bool> для нее
                        если встроенный тип умеет себя кастить, надо этим пользоваться
                        если объект имеет operator bool (), надо этим пользоваться

                        code bloat нужен только для параноидального ПО, когда неумелые преобразования типов приводят к неожиданным для программиста ситуациям - ну так и С++ не подходящий для этого язык
                        однако в 99.99% программ общего назначения (а с++ как раз язык для таких программ) параноидальность не нужна - потому что увеличивается время разработки и ухудшается читаемость программ, а профита никакого - в элементарнейших ситуациях, таких как кастинг int к bool, даже начинающий программист понимает что происходит, это соответствует стандарту и даже не приводит к UB

                        не стоит уродовать возможности языка и тем более говорить что это всё С, а не С++
                        если почитать стандарт, во многих случаях комитет даже не парится с записью с-каста как static_cast - потому что это короче, проще и опытному программисту не доставляет проблем

                        пример с double d = 2.L/1 - это от лени дописать .L в любом из операндов? если надо делить две переменных, то достаточно тоже один операнд скастить

                        в пост призывается тарас с безопасными приведениями типов
                        Ответить
                        • > потому что увеличивается время разработки и ухудшается читаемость программ

                          Не согласен.
                          Ответить
                        • > нелепо везде писать static_cast<bool> для нее
                          Полностью поддерживаю. В тех случаях где каст в бул очевиден - все понятно и без статик_каста. В тех случаях где каст не очевиден - каст не нужен ни в той ни в другой форме, и лучше применять другие средства.
                          Ответить
                          • Зачем же в С++ static_cast?
                            Ответить
                            • Кастовать указатели на объекты в некоторых случаях (когда dynamic_cast был бы оверкиллом).
                              Ответить
                              • А почему бы не кастовать скобками? везде...

                                BaseClass* B = new DerivedClass();
                                DerivedClass* A = (DerivedClass *)B;
                                Ответить
                                • Потому что dynamic_cast и reinterpret_cast <=> скобки.
                                  Ответить
                                  • бу
                                    Ответить
                                  • А static_cast нельзя заменить скобками? Так?
                                    Ответить
                                  • в некоторых случаях reinterpret как раз неявно вызывается при c-style cast в c++
                                    http://govnokod.ru/10569#comment143947

                                    а динамик каст нельзя заменить скобками, потому что скорее всего будет вызываться reinterpret (если компилятор не посчитает типы совместимыми), реже - статик
                                    Ответить
                                    • В Аде всё скобками кастуется (кроме совсем ][а|<3Pских побитовых кастов). А неявных кастов нету вообще.
                                      Ответить
                        • Скажите, пожалуйста, зачем в C++ static_cast?
                          Ответить
                          • Подозреваю, что для пользовательских типов.
                            Ответить
                            • Так и будет в коде: где-то крест, а где-то звезда.
                              Ответить
                          • сообщает компилятору о необходимости выполнения явного конкретного преобразования типов
                            например,
                            float a = 10; // неявное преобразование int к float
                            float b = static_cast<float>(10); // явное преобразование к float - не нужно, т.к. компилятор и без этого в курсе, что ему надо делать
                            double c = static_cast<float>(10); // программист требует преобразования аргумента к float (границы и обрезание точности), затем компилятор будет преобразовывать float к double
                            
                            // еще пример
                            int f(int a);
                            int f(char a);
                            int var;
                            f(var); // calls f(int);
                            f(static_cast<char>(var)); // calls f(char);

                            или вопрос был зачем вместо c-cast определили static_cast/reinterpret_cast/const_cast?
                            Ответить
                            • И это тоже
                              Ответить
                            • Да, зачем же придумывать новый каст, когда есть старый?
                              static_cast сообщает больше о действии, чем c-cast и тем паче неявная кастовка типа.
                              Хороший тон, сообщать, по-возможности, полную информацию.
                              А то смотришь какую-нибудь передачу "совершенно секретно", а там говорят: "наука не может ответить на вопрос о том, почему период обращения Луны вокруг своей оси равен периоду обращения вокруг Земли". Это нехорошо.

                              Конечно, можно сказать, что лишний каст int к bool запутывает. Это, наверно, так. Но если state -- это пользовательский тип, который нужно привести к bool, например для тоже полиморфизма символа, то так писать и нужно. И мой пример со static_cast<double> как раз и был нацелен в примитивном виде на демонстрацию сложности ощущения неявного преобразования.

                              Не следует человека заставлять думать лишнего над тем, над чем он думать не должен.

                              Говорить нужно правду, только правду и всю правду.

                              А во-вторых, менять по ходу доказательства теоремы крест на звезду, а звезду на точку -- моветон. Так же и в коде менять один вид преобразования типа на другой в разных местах программы -- неприлично. Это не нанесёт вреда читающему, но осложнит понимание.

                              Хотите c-cast и неявный каст? Добро пожаловать в C! Короткий код -- высокая производительность.
                              C++ язык более читаемый с элементами обратной совместимости, чтобы определённое множество программистов быстрее смогло на нём создавать программы.
                              Ответить
        • Имхо лучше явные методы - isOk(), isEmpty(), isFailed() и т.п. Не всегда можно понять из контекста что означает true, а что false.
          Ответить
          • Это да, это правильно! Несомненно! Сразу можно прочитать: if( State.isOk() )
            Ответить
    • Вот нафлудили-то...
      Наставили минусов и нафлудили.
      Хехе.

      PS: reinterpret_cast рулит!
      Ответить
      • Вчерашний день.
        Тут уже придумали: Вольт -- суперкаст!
        Сам всё определяет своим супервзглядом, оптимизирует всё в суперскорость и отгоняет программистов супергавком!
        Ответить
        • Во многих здравых языках обходятся одним типом каста, это только больная фантазия Страуструпа могла наплодить столько сущностей. Вы же посмотрите на фотокарточку Страуструпа, вылитый педофил.
          Ответить
          • Обходятся одним типом, потому что другие просто не нужны.
            Ну откуда будет существенный статический каст в Java, если все объекты наследуют одному, а самих объектов нет, есть только ссылки, которые всегда безболезненно одна в другую превращаются? Следить, чтобы объект в int не кастанули? Ну разве что... И reinterpret_cast в Java бессмысленный, потому что там не может возникнуть непонятной последовательности битов, там VM всё про всех знает.

            Ну и зачем Java много кастов?
            И так, я полагаю, во всех ваших "здравых" языках. Они просто не сталкиваются с ситуациями, с которыми можно столкнуться в C++, потому им и касты сложные не нужны.
            Ответить
            • Ну покажи мне пример, где static_cast действительно полезно указывать вручную, там, где сам компилятор понять не сможет? Мне тут показали, что static_cast даёт сделать то же, что и dynamic_cast, но без рантайм-проверки. Сомнительная какая-то выгода -- учитывая что сами местные ораторы уверяют, что cast'ы используются раз в год, т..е оверхед negligible. Т.е. это прематуре оптимизатион. В остальных случаях это static_cast<bool>, который сами крестушники стесняются писать и юзают страшный-ужасный си-стайл.

              Я повторяю мою мысль -- если бы я был Страуструпом и я бы сочинял суперсет Си, то я бы оставил семантику си-каста как он есть (как раз одно из тех мест, где совместимость с Си порушили) -- т.е. объединил бы static_cast<> и reinterpret_cast. А для классов заюзал бы один общий cast(). Остальное не наша забота.

              Если уж на то пошло, почему С++ позволяет виртуальным методам вызываться динамически без указания большими буквами, что это рантайм-вызов? Вполне С++ way было бы вместо obj->foo() писать dynamic_call obj->foo()! А если не хочешь виртуально -- то вызывай так: static_call obj->foo()! Подумаешь, что во втором случае может крешануться, потому что вызван не на тот derived-class! В учебнике написано, что в целом такая конструкция более безопасная, чем устарелый, никчёмный C-style call. Гы.
              Ответить
              • > используются раз в год
                > т.е. оверхед negligible
                Вы видите взаимно-однозначное соответствие между этими двумя высказываниями?
                Ответить
              • _cast haters gonna hate
                Ответить
              • Будем терпеливы.
                Объясним третий раз.
                static_cast -- это любое преобразование типа, которое нужно разрешить на этапе компиляции.
                То есть, компилятор в определённом месте, где стоит static_cast должен вывести один тип из другого.
                Это нужно, например, чтобы разрешить сложности с полиморфными символами на этапе компиляции. С тем же делением, нужно указать компилятору, что пришедшие два целых числа нужно трактовать как с плавающей точкой и вызвать нужную реализацию символа деления.
                Бывают более экзотические случаи с необходимостью приведения типа в аргументах шаблонных функций/методов. Использование "даункаста" в static_cast нужно просто для того, чтобы на этапе компиляции воспользоваться преимуществами статической типизации и определить: а вообще возможно такое присвоение? А то вдруг я где ошибся, скомпилировал, думаю, что всё ок, а там два класса из разных иерархий.

                dynamic_cast -- производит проверку совместимости контрактов в ран-тайм. То есть, уже недостаточно нам информации периода компиляции, чтобы решить этот вопрос. Программа может быть собрана из разных динамических библиотек, с разными контрактами и т.д. Но разрешимыми. И вот, в некоторых местах возникает необходимость перейти в расширенный контракт, чтобы переиспользовать код.

                reinterpret_cast -- вообще ничего не проверяет. Он используется, если уже никакой информации получить не удаётся. Вам в каком-то MPI мессадже упали биты о.О И чё? Кто скажет вам, что это такое? Строка аль массив чисел, аль еШо чего-нибудь. Никто! Вам приходится надеяться, что данные пришли доверенные и не побились. Хеш сошёлся -- пошёл каст. Он говорит: думай об этих битах, как массиве целых! Ок! Но проблемо!

                Три разных уровня возможно ошибки возникновения в коде: на этапе компиляции (можно проверить статическую типизацию), во время ран-тайм (можно выбросить исключение, если контракт неожиданный), во время исполнения, но без проверки (а потому что узнать неоткуда).
                Ответить
              • В С++ есть ключевое слово virtual. Нет virtual -- нет полиморфизма.
                Ответить
            • >Они просто не сталкиваются с ситуациями, с которыми можно столкнуться в C++,
              Ну так все эти ситуации в С++ -- от воспалённого мозга. Сами придумали проблему, сами решили. Потом сидят довольные -- какие мы умныя :)
              Ответить
          • Крестосрач продолжается? ;)
            Ответить
            • Обратите внимание на соотношение комментариев к коду до вброса static_cast и после.
              Вот она -- сила... пенопласта... :)
              Ответить
          • > только больная фантазия Страуструпа
            А ещё меня плющит от кода, набранного пропорциональным шрифтом
            Ответить

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