о современном 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-19 12:58 pm (UTC)Дык, в посте про то и говорится, что некоторые библиотеки невозможно использовать, не залезая в аццкие глубины буста, в терминах которых эта документация вынужденно сформулирована.