Оффтоп Antony Polukhin
4 419

Как мы ездили улучшать язык программирования С++

Разработчик «Яндекс.Такси» Антон Полухин — о поездке в Международный комитет по стандартизации, рассмотрении заявок на улучшение С++ и о важности этих исправлений для всех пользователей.

В закладки

Два года назад «Яндекс» объявил о создании рабочей группы для разработки стандарта языка программирования С++. Группа стала проводником для всех российских разработчиков, которые хотят внести свои предложения по улучшению языка на рассмотрение в Международный комитет по стандартизации (ISO).

Сегодня C++ — один из самых широко используемых языков программирования. На нём написан почти весь интернет и множество программ, которыми мы пользуемся каждый день.

На C++ выполнен почти весь Adobe. От качества языка зависят обновления Photoshop, Illustrator, Acrobate и Indesign — базовые инструменты для работы любого графического дизайнера и верстальщика. C++ стал основой программного обеспечения для электронной коммерции на Amazon — крупнейшем сайте, который заменил многим американцам и европейцам походы по магазинам.

Операционная система OS X, разработанная в Apple, написана не на одном языке, но, например, Finder (аналог «Проводника» на Windows) сконструирован на C++. Все файлы и папки вашего Macbook, тегирование, структурирование и поиск — всё это зависит от качества языка.

Сайт агентства Bloomberg, где в режиме реального времени публикуется вся мировая финансовая информация, файловая система и поисковик Google, «Яндекс», «Яндекс.Такси», MySQL для работы с базами данных — всё написано на C++. Язык использует NASA, Microsoft, Nokia, Vodafone, центр ядерных исследований CERN, Intel, IBM — перечислять знаменитые компании и аббревиатуры можно до бесконечности.

Появление объектно-ориентированного программирования

В незапамятные восьмидесятые годы, когда датский программист Бьёрн Страуструп начал работу над С++, компьютеры выглядели совершенно иначе и были менее производительны, чем сейчас. C++ вырос из скрещивания очень выразительного, но медленного языка «Симула-67» и C.

Язык С создавался для того, чтобы программистам не приходилось писать новую программу под каждую архитектуру компьютера, а можно было бы написать код один раз — он бы работал на любой платформе. Для того времени это был прорыв, даже сейчас язык C всё ещё используется для прошивки, например, бытовой техники и написания операционных систем.

Бьёрн Страуструп добавил в язык C парадигму объектно-ориентированного программирования. Позже российско-американский ученый Александр Степанов добавил стандартную библиотеку — набор функций, шаблонов, контейнеров и классов, которые можно применять как «черный ящик», не заглядывая внутрь, использовать уже готовые образцы.

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

Процесс стандартизации

Процесс защиты предложений на ISO не менее сложный и замысловатый, чем написание кода. Международная организация по стандартизации несколько напоминает отечественный ГОСТ. Если когда-нибудь у вас будет время, полюбопытствуйте и загляните в ГОСТ 19781-90, который кодифицирует программное обеспечение. Стандарт C++ — около полутора тысяч страниц текста, который обновляется каждые три года.

Заседания комитета проходят три раза в год. Каждый раз в новом городе и длятся по целой неделе. На заседании необходимо присутствовать очно. Довольно часто каждый рабочий день занимает более девяти часов. В комиссии сидит сам изобретатель языка Бьёрн Страуструп.

В течение дня рассматриваются комментарии — в первую очередь от стран, то есть от таких групп, как наша, которые представляют страну, а потом уже от отважных энтузиастов-одиночек. Бывает, что за день нужно обсудить 300 комментариев. Например, на встрече в ISO в Иссакуа, где обсуждался как раз C++ 17, решили сократить обеденный перерыв, чтобы больше времени осталось на разбор предложений и обработку ошибок.

Мы приезжаем на встречи вооружённые до зубов, у нас также есть правки-пожелания от всех, кто пишет на почту рабочей группы. Иногда часть простых изменений удаётся внедрить прямо на заседаниях — в качестве «редакторской правки». Так было в Иссакуа.

Матвей Корнилов из МГУ справедливо заметил, что формулу в разделе "Associated Legendre polynomials" нельзя представить в виде полинома. Редакторы стандарта сразу исправили название раздела на "Associated Legendre functions".

Мы побывали на пяти заседаниях — три из них прошли в Америке, по одному в Канаде и Швейцарии. За два года приняли шесть наших предложений — это большая цифра, учитывая, что обычно предложения могут рассматриваться по два-три года. Например, нам удалось убедить комитет решать одну из проблем другими методами, позволяющими не дублировать все контейнеры стандартной библиотеки.

Проблема контейнеров

Угроза появления дубликатов контейнеров возникла, как ни парадоксально, из-за необходимости облегчить преобразование кода на C++ в машинный код, что традиционно было ресурсозатратной задачей. В стандарте 2011 года появился спецификатор constexpr — он позволял создавать переменные и функции, а их расчёт производился на этапе компиляции.

Одно из предложений, внесённое другими на рассмотрение ISO, было создание нового контейнера, который можно использовать только в constexpr-функциях. Это необходимо для того, чтобы часть вычислений производить заранее, ещё до запуска, поставки программы, выделяя память в константные выражения. Этот контейнер дублирует контейнер vector, только предназначен для constexpr контекста.

В будущем это привело бы к тому, что все контейнеры стандартной библиотеки получили своего клона для constexpr контекста. Этого малополезного задвоения мы предложили избежать. Мы нашли способ модифицировать уже существующие контейнеры для этих же целей, создав один новый аллокатор constexpr_allocator. С его помощью можно «тюнинговать» все остальные.

Наше предложение было принято. Значит, пользователи языка будут использовать привычные классы-контейнеры, а стандартная библиотека не будет раздуваться как тесто на дрожжах.

Казус спецификатора

Ещё пять наших принятых предложений касались спецификатора constexpr. Мы предложили исправить недочёт с циклами, которые не всегда гарантированно просчитывались в процессе компиляции, хоть и были помечены constexpr. Пометить некоторые простые методы как constexpr и проработать заголовочный файл "<algorithm>", чтобы он также вписывался в контекст constexpr.

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

И последнее, что нам удалось защитить, что внесено в стандарт — это реверанс в сторону математиков и физиков, использующих программное обеспечение в повседневных исследованиях. Теперь std::complex можно использовать в constexpr — это значит, что на этапе компиляции можно делать вычисления над комплексными числами.

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

Вместо эпилога

Стандартизация языка, как построение коммунизма — процесс бесконечный. В 1994 году собирались довести до идеала С++ к следующему году. В 2003 выпустили улучшения для «идеальной версии». В 2011 году выпустили стандарт С++ 11, который даже удостоился благодарности на вручении Оскара в 2018. В 2018 году программисты-энтузиасты и мы в их числе, всё еще бьёмся над улучшениями.

Можно подумать, что мы боремся за собственное удобство, за то, чтобы нам было проще и приятнее писать код на С++. Это правда, но отчасти. C++ производительный язык, но сложный и местами громоздкий. Из-за этого страдают не только разработчики, но и вся отрасль в целом, так как на выполнение некоторых задач в идеальном мире должно уходить намного меньше времени, чем уходит сейчас.

Каждое принятое изменение — это не просто очередная программистская примочка. Каждое новшество делает процесс разработки чуть проще, логичнее и быстрее, а работу наших приложений, нашу жизнь ещё лучше и технологичнее.

Сейчас на рассмотрении комитета 12 наших предложений. Это число будет расти. Любое принятое предложение, даже любая небольшая правка делает язык C++ чуть лучше, чуть проще, чуть функциональнее.

Десяток таких правок — и ваша любимая игра уже работает быстрее, ещё десяток — и ваш телефон меньше ест батарею. Ещё сотня — и у разработчиков по всему миру появятся новые инструменты для написания программ. А с новыми инструментами откроются и новые возможности.

Материал опубликован пользователем. Нажмите кнопку «Написать», чтобы поделиться мнением или рассказать о своём проекте.

Написать
{ "author_name": "Antony Polukhin", "author_type": "self", "tags": [], "comments": 12, "likes": 26, "favorites": 1, "is_advertisement": false, "subsite_label": "flood", "id": 41631, "is_wide": false }
00
дни
00
часы
00
мин
00
сек
(function(){ var banner = document.querySelector('.teaserSberbank'); var isAdsDisabled = document.querySelector('noad'); if (!isAdsDisabled){ var countdownTimer = null; var timerItem = document.querySelectorAll('[data-sber-timer]'); var seconds = parseInt('15395' + '50799') - now(); function now(){ return Math.round(new Date().getTime()/1000.0); } function timer() { var days = Math.floor(seconds / 24 / 60 / 60); var hoursLeft = Math.floor((seconds) - (days * 86400)); var hours = Math.floor(hoursLeft / 3600); var minutesLeft = Math.floor((hoursLeft) - (hours * 3600)); var minutes = Math.floor(minutesLeft / 60); var remainingSeconds = seconds % 60; if (days < 10) days = '0' + days; if (hours < 10) hours = '0' + hours; if (minutes < 10) minutes = '0' + minutes; if (remainingSeconds < 10) remainingSeconds = '0' + remainingSeconds; if (seconds <= 0) { clearInterval(countdownTimer); } else { timerItem[0].textContent = days; timerItem[1].textContent = hours; timerItem[2].textContent = minutes; timerItem[3].textContent = remainingSeconds; seconds -= 1; } } timer(); countdownTimer = setInterval(timer, 1000); } else { banner.style.display = 'none'; } })();
{ "id": 41631, "author_id": 185263, "diff_limit": 1000, "urls": {"diff":"\/comments\/41631\/get","add":"\/comments\/41631\/add","edit":"\/comments\/edit","remove":"\/admin\/comments\/remove","pin":"\/admin\/comments\/pin","get4edit":"\/comments\/get4edit","complain":"\/comments\/complain","load_more":"\/comments\/loading\/41631"}, "attach_limit": 2, "max_comment_text_length": 5000, "subsite_id": 199791 }

12 комментариев 12 комм.

Популярные

По порядку

Написать комментарий...
1

C++ давно стал монстром, который интересен программистам только из-за совместимости с legacy кодом. вот вы, автор, знаете хотя бы одного человека, который считает что он полностью освоил C++17?

шаблоны, constexpr по сложности уже перевесили весь остальной язык вместе взятый, при этом так до конца не решая поставленные перед ними задачи

мне лично нравится подход Nim (и D?), где любой код может просто исполняться в compile-time, без всяких дополнительных constexpr обозначений; template machinery в значительной степени перенесена в библиотеки, манипулирующие AST в compile-time; а концепты оформляются просто как участки кода, которые должны успешно пройти синтаксическую проверку при подстановке в них конкретного типа.

Ответить
0

Ну у C++ хотя бы нет GC. C++ ужасен, спору нет, но пока ничего лучше не придумали.

Ответить
0

уже есть golang ))

Ответить
0

разработка софта - дело непростое. C++ решает проблему сложности, вводя всё более навороченные конструкты с зубодробительным синтаксисом. Go просто отказывается решать эту проблему в самом языке - можете пользоваться препроцессорами и генераторами кода, если хотите. Nim предлагает базовые конструкции с удобным синтаксисом и дальше переносит нагрузку на библиотеки.

просто почитайте описание языка. на мой взгляд, он сравним по объёму с C++03, может даже C++11, но при этом afaik и язык, и компилятор разрабатывает всего один человек, остальные работают только на уровне библиотек. Сравните это с тем, сколько людей в одном только комитете по C++ заседает, не говоря уж о разработчиках компиляторов.

с другой же стороны, поскольку некоторые базовые вещи done right (in particular, compile-time programming including AST analysis & transformation), он куда мощнее C++03. Вот этот уровень мне нравится - язык, который не отказывается полностью от generics как Go, но который и не делает ещё один язык в языке для реализации всех их возможностей. Вместо этого - в самом языке реализуем лишь небольшой набор фундаментальных фич и дальше даём простор авторам библиотек.

К примеру stackless coroutines реализованы библиотекой, преобразующей async/await код в автомат; более того - она же может генерить одновременно и синхронную версию из того же исходного кода, т.е. просто опустить все async/await префиксы к операциям. Или скажем аналог MOC-препроцессора из Qt тоже можно сделать библиотечной функцией, вызываемой при компиляции. Или генерить автомат из регулярки. Или видел библиотеку, которая позволяет декларативно описать дерево GUI-объектов (как в Qt Quick) и сгенерить по нему код для обычного Qt.

C++ тоже движется в этом направлении, но такое ощущение что там сидят эстеты, которые предпочитают рубить хвост собаке по частям - и даже в C++20 до сих пор нет возможности просто выполнить произвольный код из программы во время самой компиляции, не говоря уж об анализе/генерации/трансформации AST.

Ответить
0

Сравните это с тем, сколько людей в одном только комитете по C++ заседает

Вы путаете холодное с горячим. Стандартизацией занимаются представители всей индустрии, т.к. язык используется более чем 2,5 человека. У большинства компаний есть свой STL, части которого они продвигают. Плюс есть общие вещи, которые нужно согласовывать.
не говоря уж о разработчиках компиляторов.

Вы забывает, что компиляторы помимо стандартных средств оптимизации еще и предлагают LTO или вот недавний пример BOLT от facebook. Можно ли по профайлу из perf оптимизировать приложения на Nim?
C++ тоже движется в этом направлении, но такое ощущение что там сидят эстеты, которые предпочитают рубить хвост собаке по частям - и даже в C++20 до сих пор нет возможности просто выполнить произвольный код из программы во время самой компиляции, не говоря уж об анализе/генерации/трансформации AST.

Еще раз. C++ это сотни тысяч разработчиков. На Nim нет ни одного production сервиса. Язык с 30+ летней обратной совместимостью конечно же развивается медленнее.

Ответить
0

Это очень плохой пример альтернативы C++. Как альтернатива питону подойдет(теперь даже в питоне можно писать ":=").

Ответить
0

Честно говоря я на крестах не писал уже лет шесть, вот как отошел от разработки для embedded больше как то нигде не пригодился. А, ну еще трогал его в Unreal Engine. ИМХО, если надо сделать что то быстро и можно использовать не плюсы, лучше не использовать плюсы. Никому не навязываю однако :)

Ответить
0

Не только совместимость с legacy. Есть еще "You don't pay for what you don't use", это куда важнее.

Ответить
0

"C++ стал основой программного обеспечения для электронной коммерции на Amazon"- Amazon же всегда на Java ориентировался?

Ответить
3

Было бы очень странно, если бы компания масштаба Amazon ограничивалась использованием только одного языка. У любого языка есть задачи, к которым он подходит хорошо, и есть те, к которым он подходит плохо - зачем же забивать гвозди микроскопом?

Ответить
0

я не говорил, что Amazon не использует другие ЯП. Я про то, что основой стал С++.

Ответить
0

Woprosy:
1. dly kakih yazikov suschestvuet specifikazija MISRA ?
2. dly kakih yazikov MATLAB generiruet kod ?
Best regards, Andrei Miroshnichenko

Ответить
0

Прямой эфир

[ { "id": 1, "label": "100%×150_Branding_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox_method": "createAdaptive", "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfl" } } }, { "id": 2, "label": "1200х400", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfn" } } }, { "id": 3, "label": "240х200 _ТГБ_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fizc" } } }, { "id": 4, "label": "240х200_mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "flbq" } } }, { "id": 5, "label": "300x500_desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "ezfk" } } }, { "id": 6, "label": "1180х250_Interpool_баннер над комментариями_Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "ffyh" } } }, { "id": 7, "label": "Article Footer 100%_desktop_mobile", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjxb" } } }, { "id": 8, "label": "Fullscreen Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjoh" } } }, { "id": 9, "label": "Fullscreen Mobile", "provider": "adfox", "adaptive": [ "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fjog" } } }, { "id": 10, "disable": true, "label": "Native Partner Desktop", "provider": "adfox", "adaptive": [ "desktop", "tablet" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyb" } } }, { "id": 11, "disable": true, "label": "Native Partner Mobile", "provider": "adfox", "adaptive": [ "phone" ], "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "clmf", "p2": "fmyc" } } }, { "id": 12, "label": "Кнопка в шапке", "provider": "adfox", "adaptive": [ "desktop" ], "adfox": { "ownerId": 228129, "params": { "p1": "bscsh", "p2": "fdhx" } } }, { "id": 13, "label": "DM InPage Video PartnerCode", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox_method": "createAdaptive", "adfox": { "ownerId": 228129, "params": { "pp": "h", "ps": "bugf", "p2": "flvn" } } }, { "id": 14, "label": "Yandex context video banner", "provider": "yandex", "yandex": { "block_id": "VI-223676-0", "render_to": "inpage_VI-223676-0-1104503429", "adfox_url": "//ads.adfox.ru/228129/getCode?pp=h&ps=bugf&p2=fpjw&puid1=&puid2=&puid3=&puid4=&puid8=&puid9=&puid10=&puid21=&puid22=&puid31=&puid32=&puid33=&fmt=1&dl={REFERER}&pr=" } }, { "id": 15, "label": "Плашка на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byudx", "p2": "ftjf" } } }, { "id": 16, "label": "Кнопка в шапке мобайл", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "adfox": { "ownerId": 228129, "params": { "p1": "byzqf", "p2": "ftwx" } } }, { "id": 17, "label": "Stratum Desktop", "provider": "adfox", "adaptive": [ "desktop" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvb" } } }, { "id": 18, "label": "Stratum Mobile", "provider": "adfox", "adaptive": [ "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "pp": "g", "ps": "bugf", "p2": "fzvc" } } }, { "id": 19, "label": "Тизер на главной", "provider": "adfox", "adaptive": [ "desktop", "tablet", "phone" ], "auto_reload": true, "adfox": { "ownerId": 228129, "params": { "p1": "cbltd", "p2": "gazs" } } } ]
Голосовой помощник выкупил
компанию-создателя
Подписаться на push-уведомления