UB на то и UB, что синтаксически код совершенно корректен, и компилятору в общем случае просто не к чему придраться.
UB отлавливается при статическом анализе(который в грамотно настроенных проектах используется на всю катушку, ну и немного компилятором, как я подозреваю, при попытках оптимизации), динамическом (некоторые проверки навешивает на дебажный билд сам компилятор, некоторые реализованы в библиотеках, в том числе стандартной, остальное отслеживает санитайзер).
Огромная и сложная система статического контроля кода обеспечивает надежность, но разбивается о суровую действительность: примерно половина (и хорошо, если не больше) общепринятых библиотек написана на чистом C (из-за большей универсальности), вдобавок многие разработчики по-прежнему пишут на C++ в стиле "Си с классами", почти не пользуясь мощной системой типов, шаблонами, и умными указателями. Привет, undefined behavior...
Отличный мультипарадигменный язык, чертовски простой в освоении, легковесный(официальный) интерпретатор идеально подходит для встраивания и работает на всем, начиная от микроконтроллеров. Для интерпретируемого языка это чудо еще и работает весьма быстро.
Насколько я понимаю, на чистом Lua, от и до, большие системы проектируют довольно нечасто, зато как средство расширения нативных программ, написанных на том же C и C++ - применяется очень широко.
Справедливости ради, 32Гб + 1Тб памяти — это старшая модель на Интеле, ее цена — $2600, в то время как $1000 просят за девайс с 8Гб + 128Гб.
Так что честнее будет сравнивать цену младших моделей — $1000 vs $1300. У ARM версии есть даже уникальная фича, за которую (ИМХО) в принципе даже не жалко заплатить — 5G.
Ну, может, у них там чудовищный макаронный говнокод, и они боятся, что начинающие разработчики при виде такого разбегутся на условный UE, где примеры (гипотетически) более красивые? :)
Причем кмк это так же актуально и для опытных разработчиков, которые скорее тоже будут интересоваться именно кодом и интересными архитектурными решениями, и тоже могут разочароваться.
Если серьезно, я конечно не думаю что все настолько плохо, но не удивлюсь если действительно опасаются антирекламы.
На месте typename могло бы быть указано значение (Non-Type Template Argument), или имя другого ограничения(концепта). На месте concept - using, inline переменная, а то и вовсе объявление функции или типа.
C++ - очень гибкий язык, и за это приходится расплачиваться более сложным и не очень лаконичным синтаксисом.
С другой стороны, шаблонная магия как правило живет где-то в библиотеках, а прикладной код может быть вполне лаконичен.
В том-то и дело, что в C++ вместо динамической типизации при любой возможности стараются использовать статическую. И на этом поле язык действительно очень хорош.
Код некоторых страшных примеров из статьи во многих может упроститься до пары инструкций времени исполнения, либо и вовсе отработать во время компиляции(в зависимости от контекста вызова).
На самом деле, реальная реализация всего этого безобразия на реальном железе совершенно неважна, потому что переполнение знакового целого - undefined behavior, отсутствие важного для правильной работы программы ограничения.
Тот факт, что процессор хранит знаковые числа с дополнением до двойки - Вас не спасет. Преобразования с переполнением выливаются в отбрасывание компилятором условий, вызовов функций и тд (выше уже выложили пример), причем самое веселое - что теряются гарантии на правильную работу программы даже до момента вызова проблемного участка кода.
Можно быть хоть трижды знатоком физических архитектур и алгоритмов работы всех действующих компиляторов(что уже близко к невозможному, кмк), все, что это даст - лишь позволит писать программы, которые работают здесь и сейчас. Для написания действительно переносимого и безопасного кода нужно строго следовать документации на язык программирования, то есть стандарт, и не допускать UB. Это гораздо проще, чем изобретать способы решать созданные на ровном месте проблемы.
Ну так лично я себя и так считаю (относительно) профессиональным программистом-плюсовиком, стандарт почитываю при каждом удобном случае, новые фичи изучаю взахлеб. Обожаю язык и, несмотря на уже больше десяти лет практики, до сих пор узнаю о нем кучу нового :)
Я пишу в контексте преподавания и студентов, которые в любом случае после прослушивания курса будут еще много практиковаться, стажироваться и/или джуниорить - а на первой работе бест практисы перенимаются у старших коллег и программистские навыки растут очень шустро.
Но, с другой стороны, Вам ведь не требуется запихнуть весь стандарт языка от корки до корки в студентов, достаточно показать подмножество языка, достаточное для эффективного решения большинства задач. Если какая-то штука не вносит значимого улучшения в эффективность, и не может использоваться без детального объяснения принципа работы - может, и не стоит ее тогда показывать?
А насчет улучшения программы, кмк достаточно поглядывать на списки нововведений по стандартам, выбрать несколько любимых и удобных для преподавания, и по возможности писать/обновлять примеры с использованием этих нововведений и стараться соответствовать официальным гайдлайнам. Если при этом не запрещать студентам использовать последний доступный в основных компиляторах стандарт, то едва ли у кого-то повернется язык назвать Ваш курс "несовременным" :)
Извините за скомканность, советы вряд ли универсальные, но хотелось поделиться мыслями.
Хочется добавить, что это, похоже, как раз дальнейшее развитие идеи библиотеки асинхронного программирования, и именно сюда ушел автор cppcoro, Льюис Бейкер. А еще над libunifex трудится легендарный Эрик Ниблер и другие классные разработчики.
std::string_view ни при каких условиях не позволяет изменять строку, на которую ссылается, единственное, что может меняться - указатель на начало и длину при вызове методов вроде remove_prefix. Но и это можно запретить, объявив его как const.
И это логично, ведь неконстантный int или указатель на начало строки тоже могут быть спокойно изменены.
К счастью, современные пакетные менеджеры(более-менее уверенно могу говорить только о vcpkg и conan, но они не единственные) весьма успешно решают проблемы с прикручиванием к своему проекту библиотек.
Если кто-то уже завернул бибиотеки в пакет, конечно. В противном случае можно подумать, надо ли оно, и либо завернуть самостоятельно и даже опубликовать, либо подумать о переезде на что-то более широко распространенное.
Сборка же из исходников рандомных проектов, в которых могут быть задействованы "нетрадиционные" возможности системы сборки или утилиты, действительно остаётся болью.
Да, в IO функциях кастовать не воспрещается, и временами вовсе необходимо: передать массив как массив байт, а так же сделать memcpy(не reinterpret_cast!) при обратном преобразовании массива байт в объекты.
Частое же употребление кастов в прикладном коде - признак плохого дизайна. Лично у меня временами такое тоже случается и тоже подгорает, но тут надо не забывать, что плохой код у меня - мне его и переписывать, разработчики языка в этом не виноваты.
В более-мене современном виде в C++ оно появилось лет 12 назад в Boost (а первые попытки затащить были в в далёком 2003), но до реализации в стандарте ехало долго: библиотеку полировали, и тем временем учили компилятор не выдавать полотна сообщений в ответ на одну ошибку при инстанциировании шаблона.
UB на то и UB, что синтаксически код совершенно корректен, и компилятору в общем случае просто не к чему придраться.
UB отлавливается при статическом анализе(который в грамотно настроенных проектах используется на всю катушку, ну и немного компилятором, как я подозреваю, при попытках оптимизации), динамическом (некоторые проверки навешивает на дебажный билд сам компилятор, некоторые реализованы в библиотеках, в том числе стандартной, остальное отслеживает санитайзер).
Огромная и сложная система статического контроля кода обеспечивает надежность, но разбивается о суровую действительность: примерно половина (и хорошо, если не больше) общепринятых библиотек написана на чистом C (из-за большей универсальности), вдобавок многие разработчики по-прежнему пишут на C++ в стиле "Си с классами", почти не пользуясь мощной системой типов, шаблонами, и умными указателями. Привет, undefined behavior...
Можно, конечно! Или речь о каком-то другом variant?
а чем Вам Lua не угодил?
Отличный мультипарадигменный язык, чертовски простой в освоении, легковесный(официальный) интерпретатор идеально подходит для встраивания и работает на всем, начиная от микроконтроллеров. Для интерпретируемого языка это чудо еще и работает весьма быстро.
Насколько я понимаю, на чистом Lua, от и до, большие системы проектируют довольно нечасто, зато как средство расширения нативных программ, написанных на том же C и C++ - применяется очень широко.
Справедливости ради, 32Гб + 1Тб памяти — это старшая модель на Интеле, ее цена — $2600, в то время как $1000 просят за девайс с 8Гб + 128Гб.
Так что честнее будет сравнивать цену младших моделей — $1000 vs $1300. У ARM версии есть даже уникальная фича, за которую (ИМХО) в принципе даже не жалко заплатить — 5G.
Ну, может, у них там чудовищный макаронный говнокод, и они боятся, что начинающие разработчики при виде такого разбегутся на условный UE, где примеры (гипотетически) более красивые? :)
Причем кмк это так же актуально и для опытных разработчиков, которые скорее тоже будут интересоваться именно кодом и интересными архитектурными решениями, и тоже могут разочароваться.
Если серьезно, я конечно не думаю что все настолько плохо, но не удивлюсь если действительно опасаются антирекламы.
ой, это, кажется, не мне, а @Racheengel ? :)
В современных реалиях - обязательно.
На месте typename могло бы быть указано значение (Non-Type Template Argument), или имя другого ограничения(концепта).
На месте concept - using, inline переменная, а то и вовсе объявление функции или типа.
C++ - очень гибкий язык, и за это приходится расплачиваться более сложным и не очень лаконичным синтаксисом.
С другой стороны, шаблонная магия как правило живет где-то в библиотеках, а прикладной код может быть вполне лаконичен.
Можно даже ввести дополнительный концепт, и сделать код еще ближе к тому, что просят :)
Не совсем понял, что Вы имеете в виду.
Не расскажете чуть конкретнее, что именно не нравится и как, по-Вашему, эта проблема должна решаться без "сумерек рассудка"?
В том-то и дело, что в C++ вместо динамической типизации при любой возможности стараются использовать статическую. И на этом поле язык действительно очень хорош.
Код некоторых страшных примеров из статьи во многих может упроститься до пары инструкций времени исполнения, либо и вовсе отработать во время компиляции(в зависимости от контекста вызова).
На самом деле, реальная реализация всего этого безобразия на реальном железе совершенно неважна, потому что переполнение знакового целого - undefined behavior, отсутствие важного для правильной работы программы ограничения.
Тот факт, что процессор хранит знаковые числа с дополнением до двойки - Вас не спасет. Преобразования с переполнением выливаются в отбрасывание компилятором условий, вызовов функций и тд (выше уже выложили пример), причем самое веселое - что теряются гарантии на правильную работу программы даже до момента вызова проблемного участка кода.
Можно быть хоть трижды знатоком физических архитектур и алгоритмов работы всех действующих компиляторов(что уже близко к невозможному, кмк), все, что это даст - лишь позволит писать программы, которые работают здесь и сейчас. Для написания действительно переносимого и безопасного кода нужно строго следовать документации на язык программирования, то есть стандарт, и не допускать UB. Это гораздо проще, чем изобретать способы решать созданные на ровном месте проблемы.
Ну так лично я себя и так считаю (относительно) профессиональным программистом-плюсовиком, стандарт почитываю при каждом удобном случае, новые фичи изучаю взахлеб. Обожаю язык и, несмотря на уже больше десяти лет практики, до сих пор узнаю о нем кучу нового :)
Я пишу в контексте преподавания и студентов, которые в любом случае после прослушивания курса будут еще много практиковаться, стажироваться и/или джуниорить - а на первой работе бест практисы перенимаются у старших коллег и программистские навыки растут очень шустро.
Но, с другой стороны, Вам ведь не требуется запихнуть весь стандарт языка от корки до корки в студентов, достаточно показать подмножество языка, достаточное для эффективного решения большинства задач. Если какая-то штука не вносит значимого улучшения в эффективность, и не может использоваться без детального объяснения принципа работы - может, и не стоит ее тогда показывать?
А насчет улучшения программы, кмк достаточно поглядывать на списки нововведений по стандартам, выбрать несколько любимых и удобных для преподавания, и по возможности писать/обновлять примеры с использованием этих нововведений и стараться соответствовать официальным гайдлайнам. Если при этом не запрещать студентам использовать последний доступный в основных компиляторах стандарт, то едва ли у кого-то повернется язык назвать Ваш курс "несовременным" :)
Извините за скомканность, советы вряд ли универсальные, но хотелось поделиться мыслями.
Хочется добавить, что это, похоже, как раз дальнейшее развитие идеи библиотеки асинхронного программирования, и именно сюда ушел автор cppcoro, Льюис Бейкер. А еще над libunifex трудится легендарный Эрик Ниблер и другие классные разработчики.
Ну Акридерм - типичный представитель мазей с глюкокортикостероидами. Возможно, Вы уже используете один из аналогов.
std::string_view
ни при каких условиях не позволяет изменять строку, на которую ссылается, единственное, что может меняться - указатель на начало и длину при вызове методов вродеremove_prefix
. Но и это можно запретить, объявив его как const.И это логично, ведь неконстантный int или указатель на начало строки тоже могут быть спокойно изменены.
К счастью, современные пакетные менеджеры(более-менее уверенно могу говорить только о vcpkg и conan, но они не единственные) весьма успешно решают проблемы с прикручиванием к своему проекту библиотек.
Если кто-то уже завернул бибиотеки в пакет, конечно. В противном случае можно подумать, надо ли оно, и либо завернуть самостоятельно и даже опубликовать, либо подумать о переезде на что-то более широко распространенное.
Сборка же из исходников рандомных проектов, в которых могут быть задействованы "нетрадиционные" возможности системы сборки или утилиты, действительно остаётся болью.
Да, в IO функциях кастовать не воспрещается, и временами вовсе необходимо: передать массив как массив байт, а так же сделать memcpy(не reinterpret_cast!) при обратном преобразовании массива байт в объекты.
C++20 для обоих случаев даже специальные библиотечные функции получил: std::as_bytes, std::bit_cast.
Частое же употребление кастов в прикладном коде - признак плохого дизайна. Лично у меня временами такое тоже случается и тоже подгорает, но тут надо не забывать, что плохой код у меня - мне его и переписывать, разработчики языка в этом не виноваты.
В более-мене современном виде в C++ оно появилось лет 12 назад в Boost (а первые попытки затащить были в в далёком 2003), но до реализации в стандарте ехало долго: библиотеку полировали, и тем временем учили компилятор не выдавать полотна сообщений в ответ на одну ошибку при инстанциировании шаблона.
Так это ж стандартная фича для таких библиотек.