На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
Страницы: (78) « Первая ... 76 77 [78]   ( Перейти к последнему сообщению )  
> Текущий Стандарт С++ и перспективы его развития
    Цитата Qraizer @
    Я так думаю, предложение в Комитет о расширении синтаксиса ?: было, но из-за озвученных проблем, ведущих, как я в раннем в посту уже обращал внимание, к сюрпризам его отклонили, ибо вероятности программеру наглючить слишком велики. Я вот как-то даже теряюсь в том, чтобы просчитать всякоразные нюансы с выбором типа ?: и даже поведения. А что, если типы в кортеже разные? А что, если типы элементов кортежей посередине и справа не все совпадают? А вдруг там вперемежку значения и разного рода ссылки? Обычные, правосторонние, константные... Как при всём этом выполнять касты с учётом правил приоритетности от identical до ellipsis?

    На самом деле, автоматическое приведение типов, ИМХО - зло! Самое ламповое место для внезапных багов. И тут желательно делать явные касты, даже в ущерб большей писанины. Другое дело автоматическое выведение типов. Увидел auto или decltype, сразу маячок, мол "смотри, что выводится".
      Если ты о строгой типизации, то оно тоже зло. В Паскале у меня, бывало, голова кипела из-за его дурацких ругательств в адрес смешения байтов и интов, к примеру. Мне пофигу, что они разного размера, для меня они оба целые, и мне только это важно. Я не хочу думать о репрезентации типов, я хочу думать об из свойствах и взаимоотношениях.
      С этой позиции неявные касты более чем допустимы. Беда в том, что в разных ситуациях нужны и немного разные свойства и взаимоотношения, и для стандартных типов их не настроишь. Тут да, увы. Но фактически я как раз и настраиваю эти самые взаимоотношения между типами, когда пишу метакод или там перегружаю кастующие конструкторы и/или операторы. Вот этого от Плюсов отнять никак нельзя ни в коем разе.
        Я вот сейчас во всю изучаю Dart. Естественно изучаю его фичи и сравниваю с С++. На счет неявного приведения типов. Вот смотри пример "зла" :lol:

        С++

        Я спецом использовал trу-catch, просто показать, что это бесполезно, никаких исключений. Код отрабатывает и не мяукает. Выводит 44.

        ExpandedWrap disabled
          #include <iostream>
           
          int main() {
            int init = 300;
            uint8_t value;
            try {
              value = init; // <--------------------------------------------------------------
              std::cout << static_cast<int>(value) << std::endl; // выводит 44
            } catch(...) {
              std::cout << "Error" << std::endl;
            }  
            return 0;
          }


        Dart

        В Dart нет встроенных 8-битных чисел. Если извратится через библиотеки, то присвоение Uint8 = int совсем не прокатывает на этапе компиляции, ибо Uint8 - неконструируемый тип. Но я нашел вот такое "решение":

        ExpandedWrap disabled
          import 'dart:typed_data';
          import 'dart:ffi';
           
          void main() {
            int init = 300;
            Uint8List value = Uint8List.fromList([init]);
            print(value[0]); // Выводит: 44
          }

        Как резюме. Dart - в принципе новодел. Но в нем учтены различные вот такие "нюансы", чтобы неявно не делалось того, чего не ждешь. Но если хочешь именно того чего не ждешь - ищи извраты :lol:
          Осталось только пояснить, почему ты это называешь "нюансом".
            Цитата Majestio @
            Код отрабатывает и не мяукает

            -Wconversion
              Цитата Qraizer @
              Осталось только пояснить, почему ты это называешь "нюансом".

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

              Кстати "нюансом" в С++ можно назвать и объявление без явной инициализации. На сколько я помню, в Стандарте С++ неявной инициализации посвящены отдельные подразделы? Давайте проведем сравнение.

              C++

              Следующая программа завершится просто Segmentation fault. Кстати, а тут можно какое-то предупреждение для компилятора включить?

              ExpandedWrap disabled
                #include <iostream>
                 
                class Bug {
                    int number;
                  public:
                    Bug(int num):number(num) {}
                    void hello() {
                      std::cout << "Bug number:" << number;
                    }
                };
                 
                int main() {
                  Bug *bug;
                  bug->hello();
                  return 0;
                }

              Dart

              В Dart все переменные по умолчанию Null-safety. Чтобы реализовать подобный код, нужно использовать модификатор ? для снятия Null-safety. Вот пример:

              ExpandedWrap disabled
                class Bug {
                  int? number;
                  
                  Bug(int num) {
                    number = num;
                  }
                  
                  void hello() {
                    print('Bug number: $number');
                  }
                }
                 
                void main() {
                  Bug? bug;
                  bug.hello();
                }

              Но и тут просто так не прокатит. Компилятор просто выдаст ошибку:

              ExpandedWrap disabled
                main.dart:15:7: Error: Method 'hello' cannot be called on 'Bug?' because it is potentially null.
                 - 'Bug' is from 'main.dart'.
                Try calling using ?. instead.
                  bug.hello();
                      ^^^^^

              Если же мы воспользуемся "советом" компилятора, то bug?.hello(); просто не будет выполнен, и программа завершит работу.
              В общем все эти неявные неявности С++ зло :lol:

              Скрытый текст
              Кстати, я так и не понял, а почему отрабатывает следующий код? Тут должно быть неопределённое поведение, но программа не падает:

              ExpandedWrap disabled
                #include <iostream>
                 
                class Bug {
                    int number;
                  public:
                    Bug(int num):number(num) {}
                    void hello() {
                      std::cout << "Bug";
                    }
                };
                 
                int main() {
                  Bug *bug;
                  bug->hello();
                  return 0;
                }
                Цитата Славян @
                Ну или даже до 3...n значений.
                Эх...

                Да хоть 100500.
                Просто измени подход.
                Ты пытаешься писать на С.
                Попробуй на С++.
                Если необходимо менять сразу несколько значений одновременно,
                значит.. это объект.
                Объедини переменные в объект.
                Перегрузи для этого объекта операцию = ( operator=() )
                и все какие надо другие, если потребуются.
                И всё получится.
                ExpandedWrap disabled
                   s = A ? p : q;
                  Majestio, ты часто упускаешь из виду, что неопределённое поведение говорит, лишь о том, что программа не соответствует Стандарту языка. Однако не означает, что она неверна, конкретные реализации имеют право доопределить поведение для частных случаев, и на них программа, допускающая такие нарушения Стандарта, тем не менее будет корректна. Самый наитипичнейний пример — что-то типа:
                  ExpandedWrap disabled
                    *reinterptret_cast<void **>(nullptr) = ccm_ram + ccm_ram_size;
                  устанавливающий стек по reset на STM32.

                  Добавлено
                  Цитата Majestio @
                  Следующая программа завершится просто Segmentation fault. Кстати, а тут можно какое-то предупреждение для компилятора включить?
                  Неинициализированные переменные компиляторы умеют детектить настолько давно, что я уж и не знаю, как найти хоть один, который бы этого не сделал. Если же ты спросишь, почему это не ошибка, а всего лишь ворнинг, то ответ до банальности прост: это нельзя стандартизировать как ошибочное поведение, т.к. в отдельных случаях подобный под будет корректным. Поэтому это лишь неопределённое поведение. Оно следует из пункта, что UB является использование объекта, которого не существует. Прикол в том, что несмотря на отсутствие инициализирующего кода, объект всё ж может существовать. Например, уже сконструирован и прошит во флэш. Звучит странно, но это возможно и для локальных переменных на отдельных исполнительных платформах. Т.к. Стандарт не определяет размещение автоматических объектов, для них необязательно используется стек, тут надо читать ABI. И кроме того, в embedded я сам пишу линкеру скрипт, определяющий разметку адресного пространства и распределение секций исполняемого объектного кода по нему. Это тебе не hosted, где всем обычно рулит ОС.

                  Добавлено
                  В общем и целом, я уже много раз говорил, что C с Плюсами многого не могут себе позволить, просто исходя из того, для какой ниши они позиционируются. Точнее для одной из каких ниш. И Плюсы активно вытесняют C оттуда, не вытеснились разве что ленивые и консерваторы. Недаром же в Стандарте есть куча всего касательно freestanding помимо hosted. И нам неленивым реформистам нынешний вид Плюсов очень нравится. Мне вот не интересен заботливый родитель, который держит за ручку и сыпет "нельзя", "осторожно", "не так", "надень шапку", "не простудись" итд итп идр. Я работаю в сфере, где иначе просто не выйдет, ибо исполнительные окружения предъявляют, и хрен ты с этим что сделаешь.
                  Но с другой стороны, у Плюсов позиционируемых ниш пруд пруди, и ради пары особенных жертвовать нормальными методиками и парадигмами, конечно, не резон. За C ничего не скажу, ИМХО он с C99 топчется на месте, а вот Плюсы делают всё возможное, чтобы кто если б захотел, собрал себе родителя по потребностям. Моё ИМХО... нет, это понимание, выстраданное опытом, это уже не ИМХО... моё чёткое понимание философии Плюсов давно уж незыблемо: не тот хорошо знает язык, кто выштрудировал себя на Стандарте и либах, а тот, кто умеет договариваться с компилятором о разделе сфер ответственности. Я могу объяснить ему, куда ему можно лезть со своими "не упади" и "осторожно, поранишься", куда прям-таки нужно "стоять! придурок" и "хрен тебе, а не сладкое", а куда пусть не суётся вообще. Покажи мне ещё один язык с такой фичей.
                    P.S. И местами даже не соваться туда, на что в Стандарте описано как "приговаривается к пожизненному расстрелу". Плюсы вообще редко что запрещают абсолютно и навсегда, но чем опаснее хотелка, тем больше усилий требуется для её достижения. Но уж ежели кто озаботился, либо ССЗБ, либо явно не случайно это в программе появилось, по теории вероятности вселенная столько ещё не живёт.
                      Цитата Qraizer @
                      Majestio, ты часто упускаешь из виду, что неопределённое поведение говорит, лишь о том, что программа не соответствует Стандарту языка. Однако не означает, что она неверна, конкретные реализации имеют право доопределить поведение для частных случаев, и на них программа, допускающая такие нарушения Стандарта, тем не менее будет корректна.

                      Хотя вот этот ответ - не совсем корректен для этого топика. Мы же тут именно про Стандарт говорим, а не про разработку вообще.

                      Добавлено
                      Цитата Qraizer @
                      Неинициализированные переменные компиляторы умеют детектить настолько давно, что я уж и не знаю, как найти хоть один, который бы этого не сделал.

                      Кстати да ... а какой опцией компилятора (gcc, clang) этот детект включить?

                      Добавлено
                      Цитата Qraizer @
                      Мне вот не интересен заботливый родитель, который держит за ручку и сыпет "нельзя", "осторожно", "не так", "надень шапку", "не простудись"

                      Тут конечно дело вкуса. А мне последнее время начал нравится подход а-ля:

                      ExpandedWrap disabled
                        #pragma GCC diagnostic push
                        #pragma GCC diagnostic ignored "-Wключ_предупреждения"
                         
                        // Участок кода, в котором нужно подавить определенное предупреждение
                         
                        #pragma GCC diagnostic pop
                      Сообщение отредактировано: Qraizer -
                        -Wuninitialized
                        Входит и в -Wall.

                        Я вообще люблю -Werror еще включать. И даже для легаси кода постепенно к этому приходить. В большинстве случаев это помогает, а там где мешает, лучше в коде явно выключить предупреждение (сильно при этом локализовав).

                        На всякий случай еще напомню про существование clang-tidy и пр. прекрасных утилит. И все это легко интегрируется в CI/CD.

                        Честно говоря, не понимаю, как люди без этого на плюсах кодят и зачем.
                          D_KEY, благодарю!
                          0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                          0 пользователей:
                          Страницы: (78) « Первая ... 76 77 [78] 


                          Рейтинг@Mail.ru
                          [ Script execution time: 0,0982 ]   [ 16 queries used ]   [ Generated: 10.09.24, 20:03 GMT ]