На днях в Праге прошло заседание международного комитета по стандартизации C++.
?-и-и-и.
C++20 готов! Остается только поставить штамп ISO, но это чисто формальный шаг, с которым проблем быть не должно.
Поздравляю всех с этим замечательным событием! Концепции, сопрограммы, модули, диапазоны, std::format, алгоритмы constexpr new и constexpr+vector+string, datetime, jthread, span, bit_cast и много другие мелкие и крупные нововведения.
Что удалось добавить и исправить в последний момент, что предложили сломать и что все хотят видеть в C++23 — всё это под катом.
Трюки от C до C++20
В последнее время появилась традиция пугать начинающих разработчиков неопределённым поведением (UB) в C++.Пришло время это изменить! Например, этот код абсолютно действителен для C:
А вот в C++ с этим были большие проблемы.struct X { int a, b; }; X *make_x() { X *p = (X*)malloc(sizeof(struct X)); p->a = 1; p->b = 2; return p; }
C работает с байтами, а C++ — с объектами.
Но у объекта есть время жизни, и до C++20 начало жизни объекта считалось с вызова new. Комитет был серьезно обеспокоен низкоуровневой работой с байтами и простыми структурами.
Приняты улучшения, гласящие, что определенный набор функций (memcpy, memmove, malloc, Alloc_alloc, calloc, Realloc, Bit_cast) начинает время жизни объекта.
Теперь большинство низкоуровневых приемов C гарантированно работают и на C++.
bool стал более надежным в C++20
Угадайте, в чем ошибка: template <typename T, size_t N>
auto count_unique(const std::array<T, N>& v) {
return std::unordered_set<T>{v.begin(), v.end()}.
size();
}
Отвечать Если T является логическим значением и в вашей реализации стандартной библиотеки v.begin() и v.end() возвращают указатели (например, вы используете libc++ или libstdc++), то функция count_unique вернет 1. Это потому, что в std::unordered_set Указатели {v.begin(), v.end()} будут неявно преобразованы в bool, и вы получите выражение std::unordered_set {правда правда} .
Преобразования в bool теперь считаются сужающими преобразованиями.
Это позволило нам найти проблемы во многих кодовых базах (больше примеров в самом предложении).
П1957 ).
Концепции C++20 стали быстрее
До недавнего времени вы могли написать такую концепцию: template <class T>
concept Reservable = requires(T v) {
v.reserve(int{});
};
И удивитесь, что он возвращает разные результаты:
struct Test;
static_assert(!Reservable<Test>);
struct Test {
void reserve(int);
};
static_assert(Reservable<Test>);
В прошлый раз мы прислали комментарий из страны: «Сделайте так, чтобы в понятиях нельзя было использовать неполный шрифт, иначе получите множественные нарушения ODR».
Наш комментарий был отклонен, но теперь мы частично добились желаемого результата с предложением P2104. В качестве бонуса мы получаем более быструю компиляцию, поскольку теперь компиляторы могут кэшировать результаты применения концепций к типам.
Незначительные изменения в C++20
- Ranges теперь имеет метод ssize.
- Внутренние сущности связи больше не видны при создании экземпляров сущностей связи модуля (компилятор сообщит вам на этапе компиляции, что не так).
- Мы изменили правила для модулей, чтобы всем инструментам было проще работать с ними.
Давайте разберем все на C++23 или C++26?
Предложение вызвало долгие дебаты о двоичном интерфейсе приложения (ABI, не путать с API).
Были подняты интересные вопросы:
1. Мы можем полностью изменить ABI в C++23 и получить прирост производительности на 5-10%.
В этом случае все старые библиотеки C++ придется пересобирать; они не смогут связываться с библиотеками с помощью нового ABI. Вы не сможете использовать библиотеки, скомпилированные более ранними версиями C++, в проекте C++23. И конечно, всегда будет старое коммерческое ПО, которое никто не будет пересобирать, но которое будет нести свою стандартную библиотеку (да-да, видеоигры, я про вас!).
Незначительным большинством голосов мы решили не нарушать ABI в C++23.
2. Дадим пользователям гарантию, что мы постараемся не сломать/изменить ABI.
А потом решили не давать гарантию.У разных производителей разные планы для своих платформ, и иногда они могут позволить себе сломать ABI, зачастую без вреда для пользователей.
Давайте добавим noException везде?
Исторически сложилось так, что стандарт не помечал функции с предусловиями как noException, даже если они никогда не вызывают исключений.
Вот, например, оператор -> std::optional: constexpr const T* operator->() const;
constexpr T* operator->();
Requires: *this contains a value.
Returns: val.
Throws: Nothing.
Он ничего не выбрасывает, но вместо noException пишет «Выдает: Ничего», потому что есть предварительное условие «*это содержит значение».
Пользователям с noException будет понятнее.
Это хорошая идея в P1656 !
Нет!
Существует целая подгруппа SG21: Контракты, которая предлагает общий механизм проверки контрактов (предварительных и постусловий).
Обработчики контрактов могут генерировать исключение; если из функции noException выдается исключение, оно завершится с помощью std::terminate и приложение выйдет из строя.
Если вставить специальный костыль, что для контрактов исключения можно выбрасывать из функций noException. Тогда все равно все ломается, типажи ориентируются на наличие noException, и начнут вам врать, функция, помеченная noException с предусловием выдаст исключение.
Но это не самая большая проблема.
Существуют ответвления стандартных библиотек, которые в некоторых случаях уже явно вставляют проверки предварительных условий.
Например, у вас есть критически важный проект, доступность которого необходимо максимизировать.
Вы используете аналогичный форк, и если вдруг кто-то вызывает std::vector::back() для пустого вектора, то генерируется исключение, которое обрабатывается выше в коде и начинает использоваться фолбэк.
С правками от P1656 такая библиотека больше не может считаться стандартной библиотекой.
И это еще не все проблемы!.
Мало того, что дополнительные noкроме стандартной библиотеки не принесут никаких положительных эффектов в виде меньших бинарных файлов или большей производительности, мало того, что изменение ломает код как минимум двух компаний, не только уничтожает ли это один из методов использования контрактов.
и предложение уже было одобрено в двух подгруппах.
Достоинства RG21
Как всегда, мы работали в различных подгруппах, делились опытом реализации и представляли предложения, авторы которых не смогли присутствовать.Одна из выдающихся идей, которую нам посчастливилось представить, это идея Антона Жилина.
P2025 Гарантированное устранение копирования для именованных возвращаемых объектов .
Его реализация позволит создавать фабричные функции для объектов без конструкторов копирования и перемещения.
На самом деле это деструктивный ход, который негласно существовал в стандарте с середины 90-х годов и был специально запрещен некоторыми правилами языка.
Мы успешно протолкнули идею через EWG-I и руководство EWG благодаря прекрасной разработке идеи самим автором.
Остается этап CWG, и через пару встреч есть все шансы увидеть нужные слова в стандарте, и первые реализации в компиляторах.
Помимо этой идеи, мы протолкнули идею P1990R0: добавить оператор[] в std::initializer_list через LEWG-I получил полезные отзывы по P1944R0: constexpr и .
Обе идеи Даниила Гончарова имеют все шансы попасть в C++23. В области std::hash нас ждал неожиданный провал.
Обсуждение p1406r1: Добавить больше специализаций std::hash. внезапно превратился в обсуждение вырожденных крайних случаев и возможностей далекого C++2*.
В результате комитет решил ничего не менять.
С SG6 и Numbers не получилось.
Основные обсуждения ИК6 совпадали с обсуждениями ABI, что не позволило ИК6 достичь кворума.
Из-за этого p1889: Выполняется работа с числами C++ , P2010: удалить операторы iostream из P1889. И P1890: Проблемы с числовыми вычислениями в C++ не обсуждались.
Планы на C++23
С началом разработки C++20 комитет начал действовать по плану.А именно, выявить несколько больших, интересных идей для следующего стандарта, а затем на всех последующих встречах не рассматривать предложения по другим темам, если по основной уже не все обсуждено.
Для C++23 такой план только что утвердили в Праге.
Основные приоритеты C++23:
- Поддержка сопрограмм в стандартной библиотеке
- Преобразование стандартной библиотеки в модули
- Исполнители
- сеть
CppCoro .
Итак, если вы уже хотите использовать сопрограммы C++20, стоит начать с этой библиотеки.
С модулями второй момент, нужно просто сесть и сделать, особых сложностей не предвидится.
Но Исполнители — это проблема.
Их конструкция не очевидна, не охватывает всех вариантов использования, в существующем виде они никем не использовались и конструкция еще не утверждена.
Комитет также согласился определить приоритетность предложений в следующих областях:
- Отражение
- Сопоставление с образцом
- Контракты
Вместо результатов
C++20 готов, пора поработать над C++23! Следующее заседание комитета состоится летом, поэтому, если у вас есть хорошие идеи по поводу нового стандарта, поделитесь ими на stdcpp.ru и в чате Telegram ПроСхх .Ну а всем, кто хочет пообщаться с представителями комитетов вживую, загляните на митапы и конференции по C++*:
* Лайфхак: вам не нужно платить за билет на конференцию, если вы спикер.В опросе могут участвовать только зарегистрированные пользователи.
Войти , Пожалуйста.
Нужно ли ломать ABI в C++? 75,55% Да 516 24,45% Нет Проголосовали 167 683 пользователя.
160 пользователей воздержались.
В опросе могут участвовать только зарегистрированные пользователи.
Войти , Пожалуйста.
Следует ли отмечать функции с предварительными условиями как no, за исключением случаев, когда они имеют тип «Выдает: ничего» 67,97% Да 314 32,03% Нет 148 Проголосовали 462 пользователя.
238 пользователей воздержались.
Теги: #программирование #C++ #IT-стандарты #стандартизация #coroutine #компиляторы #библиотеки C++ #malloc #standard #c++20 #coroutines #c++23 #ranges #modules #concepts #abi c++ #abi #contracts
-
Когда Черный Не Черный?
19 Oct, 24 -
Нигма Расшифрует Аббревиатуры
19 Oct, 24 -
Расширение Возможностей Cleantalk Anti-Spam
19 Oct, 24