С++20 на подходе! Встреча в Рапперсвил-Йона

ATR

Величайший
PR-group
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
ДРУЗЬЯ ФОРУМА

ATR

Величайший
PR-group
ПРОВЕРЕННЫЙ ПРОДАВЕЦ
ДРУЗЬЯ ФОРУМА
Регистрация
30 Июн 2018
Сообщения
2,003
Реакции
722
Репутация
16
В начале июня в городе Рапперсвил-Йона завершилась встреча международной рабочей группы WG21 по стандартизации C++.



Контракты

В C++20 приняли контракты. А значит можно будет в скором времени забыть про использование макросов для ассертов, получить лучшую документацию из коробки и даже заметить прирост производительности. Выглядят контракты на практике вот так:

1.png
В описании выше, всё что в двойных квадратных скобках, является контрактами. Так вот, из них:
  • Компилятор (в зависимости от флагов компиляции) сгенерирует ассерты
  • Компилятор (в зависимости от флагов компиляции) сможет делать выводы и оптимизировать код на основе их. Так например, сможет полностью удалить проверку на пустоту возвращаемого значения в пользовательском коде
  • Сторонняя утилита (например doxygen) сможет сгенерировать более полную документацию в функции, без необходимости явно прописывать пред/пост условия
  • Статические анализаторы смогут проанализировать код и найти ситуации, когда предусловие гарантированно нарушается (да, без всяких рантайм тестов)
Подробности по контрактам доступны

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

На помощь контрактам спешит библиотека от

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

и

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

, позволяющая сохранять и печатать стектрейс. Так можно будет задать обработчик проваленного контракта и печатать в нём последовательность вызовов, которая привела к проблеме:

2.png
При нарушении контракта, мы увидим подобное сообщение:

Screenshot_1.png
std::stacktrace ещё не принят в C++20, но прошёл design review в группе LEWG и осталась только работа по приведению его описания в соответствие с правилами стандарта в группе LWG. Последняя спецификация доступна

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

Концепты

Концепты, как фича языка, были уже приняты на прошлом заседании комитета, а в этот раз в стандартную библиотеку приняли основные концепты из Ranges TS. Так что теперь можно пользоваться готовыми концептами для описания compile-time требований к шаблонным параметрам и не мучатся с написанием собственных:

Screenshot_2.png
Feature-test macros

Уже длительное время компиляторы и стандартные библиотеки предоставляют макросы, для описания возможностей компилятора. Теперь эти макросы официально являются частью стандарта и даже были расширены. Так теперь можно проверить поддержку компилятором аттрибута unlikely используя выражение __has_cpp_attribute(unlikely).

Список макросов принятых на заседании

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

bit_cast

Использование reinterpret_cast для преобразования одного тривиально копируемого типа в другой — очень плохая идея. Но искушение велико и многие разработчики это делают. Поэтому комитет C++ сделал функцию специально для таких случаев.

Использовать её легко, просто замените

Screenshot_3.png
Теперь, если размеры some_array и my_type не совпадают, или если вы пытаетесь преобразовать не тривиально копируемые типы — вы получите сообщение об ошибке на этапе компиляции. В остальных случаях — вы избежите всех страшных ошибок связанных с type aliasing.

Алгоритмы и новые функции

Вот некоторые полезные вещи, добавленные в стандартную библиотеку C++20:
  • shift_left(it_begin, it_end, unsigned n) — сдвигает значения в диапазоне влево на n, как если бы вызывали *it_begin = std::move(*(it_begin + n)), *(it_begin + 1) = std::move(*(it_begin + n + 1))...
  • shift_right(it_begin, it_end, unsigned n) — аналогично алгоритму выше, но двигает диапазон право, как если бы вызывали *(it_begin + n) = std::move(*it_begin), *(it_begin + n + 1) = std::move(*(it_begin + 1))...
  • ispow2(x) — вернёт true если в него передали число, являющееся степенью двойки
  • ceil2(x) — округляет число в большую сторону до ближайшего числа, являющегося степенью двойки
  • contains — все ассоциативные контейнеры обзавелись функцией bool contains(const key& v), которая возвращает true если ключ содержится в контейнере

В добавок, уже имеющиеся алгоритмы использующие std::swap и сам std::swap стали constexpr. Так что теперь можно сортировать, вызывать std::nth_element и получать их результаты на этапе компиляции. Все подробности доступны

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

от РГ21.

atomic_ref

Вы работаете со структурами данных в основном из одного потока, но в какой-то момент вам необходимо работать с полем атомарно? Для этих случаев был добавлен шаблонный класс atomic_ref<T> (формальное описание доступно

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

).

При этом надо помнить, что атомарность гарантируется только для операций производимых через экземпляры классов atomic_ref<T>. Так что если вы в одном потоке пишете в переменную без atomic_ref, а в другом потоке читаете через atomic_ref — то в итоге ничего хорошего не получится.

Кстати, если вам не нравятся неконсистентные имена типов (string_view, atomic_ref), то выскажите своё недовольство

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. Если будет достаточное количество голосов, постараемся все имена привести к одному виду.

Экземпляры классов как шаблонные параметры

Если вы написали класс X, и для него написали operator<=> следующего вида:

Screenshot_4.png
Однако комитету ещё предстоит большая работа по модернизации стандартной библиотеки и переводу различных её частей на использование operator<=>.

constexpr virtual

Ограничения для функций, выполняемых на этапе компиляции, были ослаблены и теперь можно писать классы с constexpr виртуальными функциями.

При этом если в базовом классе у вас имеется метод constexpr virtual int foo();, то в наследнике int foo() может быть как constexpr, так и нет. При вызове foo() на этапе компиляции компилятор не даст вам скомпилировать программу, если вы будете пытаться выполнить не constexpr виртуальную функцию.

Данное изменение, например, открывает двери для реализации применимого на этапе компиляции std::type_info, что позволит этому классу получить функционал

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

, с возможностью гарантированной compile-time работы с типами:

Screenshot_5.png

Последние подробности доступны

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.
Parallelism 2, Reflection и Executors TS

Parallelism 2 всё ещё готовится к выходу немного,c 22 марта 2018 поправили type traits связанные с simd да добавили функционала для векторных инструкций.

Reflection готовится к выпуску в виде технической спецификации (TS). В нём рефлексия делается всё ещё через механизмы схожие с <type_traits>. В планах донести до ядра языка больше функционала для constexpr вычислений и переделать рефлексию на constexpr! функции (см. ниже).

Executors в C++20 скорее всего не попадут. Скорее всего они будут выпущены в виде отдельного TS. Возможно что весь их дизайн будет пересмотрен и упрощён.

user-declared virtual destructor и тривиальность типа

Изменение, которое должно попасть в C++20 (на следующем заседании) повлияет на производительность различных частей стандартной библиотеки и оптимизации компиляторов, но вряд ли будет заметно в повседневной разработке:

Screenshot_6.png
Идея в том, что если деструктор виртуальный, это ещё не значит что он не тривиальный. Так стандартная библиотека сможет понимать, что тип с которым она работает хоть и имеет виртуальный деструктор, на самом деле не требует вызова деструктора для освобождения ресурсов. Это может дать прирост производительности например для std::vector<Base>, где Base имеет такой виртуальный деструктор.

constexpr!

Ещё одно занятное изменение, которое рассматривается для приёма в C++20 — это constexpr! функции.

Такие функции обязаны выполняться только на этапе компиляции, любая попытка использовать их в runtime приведёт к ошибке компиляции. Это одно из изменений необходимых для рефлексии в C++.

Дополнительным бонусом constexpr! функций является их эффективное использование ресурсов компилятора. Т.к. constexpr! функции не выполняются на рантайме, компилятор не должен генерировать промежуточное представление (машинные инструкции) для них и не должен держать их памяти или оптимизировать. Это резко уменьшает количество оперативной памяти, требуемой компилятору и несколько ускоряет компиляцию. Должно оказывать ощутимый эффект на современные библиотеки, сильно полагающиеся на метапрограммирование, как

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

или

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

.

Вместо итогов: constexpr std::regex

Множество языков программирования в данный момент компилируют/транслируют регулярные выражения ещё перед запуском программы. Таким образом, когда программа стартует, все регулярные выражения уже преобразованы в соптимизированный конечный автомат.

В C++ это не так:

Screenshot_7.png
В коде выше конечный автомат из регулярного выражения будет строится при первом заходе в функцию is_valid_mail(). Это долгая операция, которая в добавок будет выполняться в критической секции.

С готовящимися новинками для constexpr вычислений (constexpr new, is_constexpr_evaluated() и др.) можно будет в C++ делать множество вещей на этапе компиляции, в том числе можно будет сделать constexpr std::regex.

С constexpr std::regex конечный автомат для функции is_valid_mail() построится ещё на этапе компиляции. Более того, GCC сможет генерировать оптимизированные регулярки на этапе компиляции без static const, т.к. начиная с GCC-6 если у constexpr функции все параметры на вход — константы, GCC форсирует вычисление на этапе компиляции.

Так вот,

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

?

P.S.: Для желающих денег C++ практики, с недавнего времени есть

Пожалуйста Авторизуйтесь или Зарегистрируйтесь для просмотра скрытого текста.

. Можно будет вооружиться и побеждать соперников используя C++17.


antoshkka​
 
Сверху