- PVSM.RU - https://www.pvsm.ru -

Привет! На связи Антон Полухин из Техплатформы Городских сервисов Яндекса. Сегодня я расскажу о ноябрьской встрече Международного комитета по стандартизации языка программирования C++, в которой принимал активное участие. Это была первая из встреч, связанных с «полировкой» C++26. Другими словами, новые фичи C++ пока не появятся — комитет должен только проработать замечания всех стран-участников, включая наши замечания от России.
Однако от плана немного отступили и втащили некоторые новинки как ответы на пожелания участников комитета:
std::integer_sequence оброс новой функциональностью,
std::format научился в constexpr.
Помимо этого поправили множество багов, перековыряли связку Hardening + Contracts, внесли улучшения во многие части стандартной библиотеки.
В P1789 [1] std::integer_sequence обзавёлся методами, позволяющими использовать его в structured binding и template for:
constexpr auto [...index] = std::make_index_sequence<COUNT>();
// Теперь с `index` можно работать как с обычным pack
auto sum = (index + ...); // 0 + 1 + 2 + 3 + 4 +...
// Или даже вот так:
template for(constexpr size_t index : std::make_index_sequence<COUNT>()) {
foo<index>(std::get<index>(some_tuple));
}
Новинка будет особенно полезна для рефлексии. Она позволит писать код компактнее, без лямбд для раскрытия std::integer_sequence:
constexpr auto members = nonstatic_data_members_of(
^^Aggregate,
std::meta::access_context::unchecked()
);
constexpr auto [...indexes] = std::make_index_sequence<members.size() / 2>();
serialize_first_half(aggregate.*[:members[indexes]:]...);
Большая радость (!) для всех пользователей: std::format научился работать в constexpr. Разве что с одним ограничением: нельзя форматировать с помощью локалей или чисел с плавающей точкой. Но даже с таким ограничением открывается большое окно возможностей: например, можно реализовать более продвинутые сообщения об ошибках в ваших библиотеках. Так, в 🐙 userver FastPimpl [2] вместо...
// Use a template to make actual sizes visible in the compiler error message.
template <std::size_t ActualSize /* ... */>
static void Validate() noexcept {
static_assert(
Size >= ActualSize,
"invalid Size: Size >= sizeof(T) failed"
);
// ...
}
...можно будет по-человечески написать:
// Use a template to make actual sizes visible in the compiler error message.
template <std::size_t ActualSize /* ... */>
static void Validate() noexcept {
static_assert(
Size >= ActualSize,
std::format("Size should be set to at least {}.", ActualSize).c_str()
);
// ...
}
Больше деталей в P3391 [3].
Контракты C++ — одна из самых ожидаемых и при этом самых холиварных фич C++26. Поэтому подгруппа Evolution целых два дня работала над различными замечаниями от стран по контрактам.
Практически все замечания были отклонены на голосованиях. Одно из ярких исключений — hardening стандартной библиотеки через контракты.
История тут приключилась, на мой взгляд, занятная: некоторые страны хотели отвязать hardening стандартной библиотеки от механизма контрактов, некоторые (например, мы) хотели сохранить возможность кастомизировать поведение при срабатывании ассерт’а в стандартной библиотеке. А вот сами разработчики стандартных библиотек C++ заметили, что hardening с контрактами... не работает.
Засада крылась в формулировках:
Hardening — это про терминирование приложения в случае нарушения контракта стандартной библиотеки.
Контракты — это про возможность обнаруживать нарушения контракта и реагировать на них.
В итоге в стандарт закралось то, чего никто не хотел. А именно: «Стандартная библиотека считается hardened, даже если нарушение контракта просто логируется». При этом неопределённое поведение при использовании стандартной библиотеки оставалось: приложение продолжало работать, но при этом делать неожиданные вещи.
Как итог, на встрече единогласно приняли P3878 [4]: «Стандартная библиотека считается hardened, если приложение терминируется при нарушении контракта». Таким образом, мы закрыли сразу пять замечаний от стран-участников.
Trivial relocation в С++26 не будет. Было решено его удалить, так как практически все разработчики компиляторов сообщили, что есть платформы и ситуации, в которых текущее поведение trivial relocation невозможно реализовать.
Trivial relocation будет дорабатываться уже для C++29, а не в C++26 P3920 [5].
Один из вопросов от участников из России был таким: «Если теперь рефлексия С++26 позволяет делать statefull metaprogramming, то не надо ли закрыть Core issue 2118 [6], который пытается запретить statefull metaprogramming через friend injection?»
Вопрос важен в частности для пользователей библиотеки Boost.PFR, которая как раз может использовать хитрость из бага CWG2118 для рефлексии агрегатов в C++14.
Ответ Core: «Техника, описанная в CWG2118, позволяет намного больше, чем C++26 reflection. В частности, C++26 reflection injection не может вырваться за пределы класса или функции. При этом CWG2118 слишком строг в текущей формулировке, но закрывать как Not a Defect мы его не готовы».
Хорошо, что Boost.PFR работает и без использования хаков из CWG2118.
optional<T&> теперь обязан быть trivially copyable P3836 [7];
добавлены std::move и noexcept для различных flat_* контейнеров P3567 [8];
std::execution::when_all теперь отправляет стоп-сигналы, только если один из «детей» их отправляет P388 [9];
atomic_ref<T> научился конвертироваться в atomic_ref<const T> P3860 [10].
И ещё почти сотня менее заметных багфиксов, доработок и улучшений.
Работа комитета не останавливается, подгруппы разбирают баги в онлайне. Сделать предстоит много: всего к C++26 было отправлено более 400 замечаний [11].
Остаётся нерешённым множество важных для нас комментариев, которые влияют на производительность и надёжность программ на C++. В частности, на этом заседании не дошли руки до P3725 [12], который делает надёжный и безопасный std::ranges::filter, не подверженный проездам по памяти и Segmentation Fault в примерах наподобие:
std::vector<std::string> coll1{"Amsterdam", "Berlin", "Cologne", "LA"};
// Перемещаем длинные строки в обратном порядке в другой контейнер
auto large = [](const auto& s) { return s.size() > 5; };
auto sub = coll1 | std::views::filter(large)
| std::views::reverse
| std::views::as_rvalue
| std::ranges::to<std::vector>();
А в скором времени пройдут конференции по C++, где можно будет поймать представителей РГ21 [13], задать им вопросы, узнать что-то новое и интересное.
22 ноября → YADRO System Level Meetup [14];
15 декабря → Встреча РГ21 [15].
Буду рад встрече!
P.S.: некоторые ссылки на P???? документы могут ещё не работать, т.к. они не опубликованы. Со временем ссылки заработают
Автор: antoshkka
Источник [16]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/reflection/437641
Ссылки в тексте:
[1] P1789: https://wg21.link/P1789
[2] 🐙 userver FastPimpl: https://github.com/userver-framework/userver/blob/develop/universal/include/userver/utils/fast_pimpl.hpp
[3] P3391: https://wg21.link/P3391
[4] P3878: https://wg21.link/P3878
[5] P3920: https://wg21.link/P3920
[6] Core issue 2118: https://cplusplus.github.io/CWG/issues/2118.html
[7] P3836: https://wg21.link/P3836
[8] P3567: https://wg21.link/P3567
[9] P388: https://wg21.link/P388
[10] P3860: https://wg21.link/P3860
[11] было отправлено более 400 замечаний: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/n5028.pdf
[12] P3725: https://wg21.link/P3725
[13] РГ21: https://stdcpp.ru/
[14] YADRO System Level Meetup: https://meetups.yadro.com/cpp-kernel-msk-1125/?utm_source=habr&utm_medium=referral&utm_campaign=System_Level_11_2025_Polukhin
[15] Встреча РГ21: https://dev.go.yandex/events/vstrecha-rg21-cpp?utm_source=habr&utm_medium=social&utm_campaign=rg21_cpp_1225&utm_content=article
[16] Источник: https://habr.com/ru/companies/yandex/articles/966574/?utm_source=habrahabr&utm_medium=rss&utm_campaign=966574
Нажмите здесь для печати.