о современном C++ и его сложности
Sep. 16th, 2017 06:28 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
(будет интересно программистам на C++ и вряд ли кому еще)
Автор заметки std::visit is everything wrong with modern C++ несколько преувеличивает масштабы проблемы, но проблема тем не менее существует и реальна. Он пишет про новый тип std::variant в C++17, который позволяет сохранять в одном значении один из нескольких разных типов. В старом добром C такое делали втыканием внутрь структуры одновременно union и переменной, означающей, какой из членов union реально присутствует. std::variant позволяет добиться примерно того же, но с статической проверкой корректности. При том, что проверить наличие конкретного варианта внутри std::variant легко и понятно с помощью std::get, хочется также иметь возможность сделать аналог switch, выполняющий разные действия для разных вложенных вариантов - так, чтобы компилятор проверял, что все варианты указаны. И вот это, пишет автор, комитет по разработке C++17 сделать убедительно не смог - либо надо писать громоздкий класс с переопределением оператора вызова (), либо вообще заниматься какой-то прикладной магией типа рекурсивных темплейтов.
С одной стороны, он прав. В том виде, в каком std::visit сейчас существует, им неудобно пользоваться, и это упущение со стороны комитета (которое, возможно, будет исправлено). Но он неправ, когда пишет, что эта ужасная сложность самого языка показывает, что C++ двигается в неправильном направлении... это поезд, который давно ушел. C++ был слишком сложным языком для простых смертных в 2014-м году. До этого он был слишком сложным языком для простых смертных в 2011-м году, а до этого он был слишком сложным языком для простых смертных в 1998-м году, и сказать по правде, он был слишком сложным языком для простых смертных где-то так в 1990-м году уж точно.
Стратегия выживания и написания серьезного размера базы кода под C++ всегда заключалась в том, чтобы из ста цветов его возможностей (большинства цветущих, некоторых уже увядших, других только раскрывающихся) выбрать относительно вменяемое подмножество и стараться не выходить за его рамки. В этом смысле большая часть работы комитета C++ в последние годы повторяет формулу успеха, с которой STL завоевала рынок библиотек C++ в 90-е.
А именно, формула такая: простой интуитивный API, предсказуемое и прозрачное использование памяти и копирование объектов; а если для воплощения всего этого нужна продвинутая магия, пользователю не нужно о ней знать. Магия остается спрятанной в исходниках библиотеки.
Это было верно в отношении std::string, std::vector и std::pair еще в 90-х. Для того, чтобы их написать, включая удобные методы их использования, нужно было знать много трюков и хитрых углов стандарта. Для того, чтобы использовать, нужно было просто интуитивно представлять строку как объект, сам хранящий память и расширяющий ее по мере надобности, вектор как очевидный аналог массива объектов итд.
Это остается верным в отношении std::unique_ptr и std::optional сегодня. Если читать их исходники, то можно ошибиться и на секунду подумать, что забрел в какой-то проект на Скале. Зато использование вполне интуитивно.
std::variant немного выбивается из этого паттерна, особенно в том, что касается проблемы "посещения всех альтернатив", и близок скорее к философии Boost - откуда он и взят почти без изменений, собственно. То, что C++{11,14,17} в целом сопротивлялись Boost-ификации языка и выносу продвинутой магии на поверхность, там, где программистам нужно постоянно с ней сталкиваться - одна из причин успеха современного C++.
Не верите мне? Спросите Джона Кармака:
Автор заметки std::visit is everything wrong with modern C++ несколько преувеличивает масштабы проблемы, но проблема тем не менее существует и реальна. Он пишет про новый тип std::variant в C++17, который позволяет сохранять в одном значении один из нескольких разных типов. В старом добром C такое делали втыканием внутрь структуры одновременно union и переменной, означающей, какой из членов union реально присутствует. std::variant позволяет добиться примерно того же, но с статической проверкой корректности. При том, что проверить наличие конкретного варианта внутри std::variant легко и понятно с помощью std::get, хочется также иметь возможность сделать аналог switch, выполняющий разные действия для разных вложенных вариантов - так, чтобы компилятор проверял, что все варианты указаны. И вот это, пишет автор, комитет по разработке C++17 сделать убедительно не смог - либо надо писать громоздкий класс с переопределением оператора вызова (), либо вообще заниматься какой-то прикладной магией типа рекурсивных темплейтов.
С одной стороны, он прав. В том виде, в каком std::visit сейчас существует, им неудобно пользоваться, и это упущение со стороны комитета (которое, возможно, будет исправлено). Но он неправ, когда пишет, что эта ужасная сложность самого языка показывает, что C++ двигается в неправильном направлении... это поезд, который давно ушел. C++ был слишком сложным языком для простых смертных в 2014-м году. До этого он был слишком сложным языком для простых смертных в 2011-м году, а до этого он был слишком сложным языком для простых смертных в 1998-м году, и сказать по правде, он был слишком сложным языком для простых смертных где-то так в 1990-м году уж точно.
Стратегия выживания и написания серьезного размера базы кода под C++ всегда заключалась в том, чтобы из ста цветов его возможностей (большинства цветущих, некоторых уже увядших, других только раскрывающихся) выбрать относительно вменяемое подмножество и стараться не выходить за его рамки. В этом смысле большая часть работы комитета C++ в последние годы повторяет формулу успеха, с которой STL завоевала рынок библиотек C++ в 90-е.
А именно, формула такая: простой интуитивный API, предсказуемое и прозрачное использование памяти и копирование объектов; а если для воплощения всего этого нужна продвинутая магия, пользователю не нужно о ней знать. Магия остается спрятанной в исходниках библиотеки.
Это было верно в отношении std::string, std::vector и std::pair еще в 90-х. Для того, чтобы их написать, включая удобные методы их использования, нужно было знать много трюков и хитрых углов стандарта. Для того, чтобы использовать, нужно было просто интуитивно представлять строку как объект, сам хранящий память и расширяющий ее по мере надобности, вектор как очевидный аналог массива объектов итд.
Это остается верным в отношении std::unique_ptr и std::optional сегодня. Если читать их исходники, то можно ошибиться и на секунду подумать, что забрел в какой-то проект на Скале. Зато использование вполне интуитивно.
std::variant немного выбивается из этого паттерна, особенно в том, что касается проблемы "посещения всех альтернатив", и близок скорее к философии Boost - откуда он и взят почти без изменений, собственно. То, что C++{11,14,17} в целом сопротивлялись Boost-ификации языка и выносу продвинутой магии на поверхность, там, где программистам нужно постоянно с ней сталкиваться - одна из причин успеха современного C++.
Не верите мне? Спросите Джона Кармака:
Saw comment // NEW BOOST CODE, and had a moment of panic before realizing it was vehicle boost, not C++ boost
— John Carmack (@ID_AA_Carmack) June 15, 2011
no subject
Date: 2017-09-16 05:32 pm (UTC)no subject
Date: 2017-09-16 05:55 pm (UTC)По-видимому, потому, что он практически изначально был двумя языками в одном - языком прикладного программирования и языком программирования прикладных интерфейсов.
С появлением templates и развитием их возможностей к ним добавился язык мета-программирования, и все три объединены общим парсером и необходимостью поддерживать совместимость с Си. Так что, безусловно, выбор относительно вменяемого подмножества для каждой из подзадач программирования и удерживание в их рамках - единственный разумный подход.
Но синтаксическое безумие, к которому приходится прибегать при метапрограммировании, начинает утомлять.
no subject
Date: 2017-09-16 07:06 pm (UTC)no subject
Date: 2017-09-16 07:19 pm (UTC)no subject
Date: 2017-09-16 05:58 pm (UTC)no subject
Date: 2017-09-16 07:05 pm (UTC)no subject
Date: 2017-09-16 07:21 pm (UTC)no subject
Date: 2017-09-16 08:10 pm (UTC)captcha: avenida heritage ;)
no subject
Date: 2017-09-17 06:18 am (UTC)no subject
Date: 2017-09-16 07:53 pm (UTC)no subject
Date: 2017-09-16 08:08 pm (UTC)no subject
Date: 2017-09-16 08:06 pm (UTC)Он был слишком простой в 1990. Недостаточно поддержанным.
no subject
Date: 2017-09-17 08:34 am (UTC)no subject
Date: 2017-09-17 09:32 am (UTC)Брррр
Date: 2017-09-17 02:31 pm (UTC)Вместо того, чтоб поддерживать этого франкенштейна и "развивать", следовало бы бросить усилия на тот же раст или смолток, или аду, или даже паскаль - пользы было б в разы больше.
no subject
Date: 2017-09-17 02:59 pm (UTC)Ужасно конечно выглядит эта попытка, и это действительно проблема но не языка а самой комити - очень уж много куда лезла и улучшала (на мой взгляд простого юзера) и считала что си должен мочь все и для всех. Но вроде как остановились теперь.
no subject
Date: 2017-09-18 05:48 am (UTC)Конечно, если у РК86 можно было полностью дизассемблировать и прочитать monitor, у msdos знать таблицу функций 21-го прерывания, то потом всё знать уже стало невозможно, приходится полагаться на то, что всякие библиотеки и фреймворки работают в соответствии с документацией. Тем не менее, мне кажется, что хороший программист при написании кода хотя бы в общих чертах представляет себе, что получится в результате компиляции. Правильно ли ориентироваться на то, что программист этого всё равно не представляет, и скрывать всю магию внутри библиотек - не знаю, не уверен.
Нереально же
Date: 2017-09-18 06:07 am (UTC)no subject
Date: 2017-09-19 12:58 pm (UTC)Дык, в посте про то и говорится, что некоторые библиотеки невозможно использовать, не залезая в аццкие глубины буста, в терминах которых эта документация вынужденно сформулирована.
no subject
Date: 2017-09-18 03:14 pm (UTC)no subject
Date: 2017-09-23 07:50 am (UTC)