понедельник, 23 июня 2025 г.

[prog.c++] Есть ли теперь смысл при разработке C++ библиотек придерживаться не самых свежих стандартов?

В заголовок поста вынесен вопрос, который занимает меня в последние пару-тройку лет. A последний год так точно.

Поясню в чем дело.

В C++ на протяжении десятков лет есть специфическая картина: существует официальный С++ на "бумаге", т.е. описанный в соответствующем стандарте, будь то С++98, С++11 или C++23, и есть реальный C++, доступный конкретному разработчику в конкретном компиляторе. И, как правило, в имеющихся в нашем распоряжении компиляторах далеко не все фичи из самого последнего официального стандарта реализованы.

Эта картина особенно важна при разработке кросс-платформенных библиотек. Если ты хочешь, чтобы твою библиотеку использовали разные люди в разных проектах и на разных платформах, то ты вынужден занижать версию стандарта. Например, вместо C++23 (который вроде как уже два года нам доступен) делать библиотеку на C++17 или даже C++14.

При разработке софта для конечного пользователя ситуация, зачастую, гораздо проще: очень часто софт пишется под конкретную платформу и вполне можно заложиться на конкретный компилятор. Но с разработкой библиотек не так. В проекте X библиотека может работать уже в режиме C++23, тогда как в проекте Y -- все еще в C++17.

До недавнего времени я воспринимал такую ситуацию как данность. Типа в разработке прикладного софта для конечного пользователя своя специфика, а при разработке библиотек -- своя. Нужно смириться и получать удовольствие.

Но после C++20 смиряться все сложнее.

C++11 стал совсем другим языком в сравнении с C++98. Два следующих стандарта, C++14 и С++17, инкрементально улучшали C++, но не могу сказать, что они переводили язык на какой-то принципиально другой уровень (даже не смотря на такие крутые фичи C++17 как structured binding и if constexpr). А вот начиная с C++20 все принципиально поменялось:

  • C++20 добавил концепты и operator spaceship (про модули промолчу ибо не пробовал);
  • С++23 добавил deducing this. Не смотря на то, что (на мой взгляд) сделали это через одно место (и можно было бы по-другому), но таки важную реальную проблему эта фича решает;
  • С++26 добавляет compile-time рефексию и, я очень надеюсь, контракты.

Все это вместе, не побоюсь этого слова, делает из C++ совсем другой язык в такой же степени, как C++11 после C++98. Если не в большей.

И вот глядя на все это великолепие в свежих стандартах С++ я не могу найти для самого себя ответ на вопрос: а зачем на при разработке своих библиотек оставаться на C++17/14/11?

Вот реально.

Ладно бы нам за наши OpenSource проекты платили. Но этого нет. И RESTinio, и SObjectizer приносят нам деньги не напрямую, а приводя к нам клиентов через репутацию. Зачастую новые фичи в тот же SObjectizer добавляются "just for fun" -- просто что-то выглядит интересным или представляет из себя вызов, поэтому делаешь это ради получения удовольствия.

И если уж удовольствие от разработки выходит на передний план, то зачем лишаться концептов, контрактов или рефлексии? Ради чего?

Поэтому чем дальше, тем больше мыслей о том, чтобы в следующем году перевести SObjectizer сразу на C++26. На счет RESTinio ситуация посложнее, но если представиться возможность плотно поработать над RESTinio, то и там тоже можно будет сразу же брать С++26.

PS. Простите, что поминаю Rust в суе, но после добавления в C++ рефлексии тема выбора между Rust и C++ становится еще более сложной, а аргументов в пользу Rust-а -- еще меньше. При этом, если бы мне пришлось программировать не на C++, а на чистом Си, то я бы однозначно предпочел бы Rust.

Комментариев нет: