C++20 всё ближе. Встреча в Джексонвилле

В начале марта в американском городе Джексонвилле завершилась встреча международной рабочей группы WG21 по стандартизации C++. На встрече добавляли фишки в C++20, подготавливали к выпуску «превью» новых компонентов и полировали до блеска шероховатости языка.

Хотите посмотреть на новости и узнать:

  • Почему это тут золотая медаль справа?
  • Как там поживает кросплатформенный SIMD?
  • Что будет если 4000 поделить на последнюю пятницу февраля?
  • Какие подводные камни нашлись у сопрограмм?
  • Какие крутые фишки для многопоточного программирования будут в скором времени доступны?

Календари и временные зоны

Смотрите как красиво и легко теперь можно задавать даты в C++20:

using std::chrono; year_month_day ymd = 2016y/May/29d; // 2016-05-29

Нужно работать ещё и с миллисекундами, да ещё и в часовом поясе Токио? Без проблем:

auto tp = sys_days{ymd} + 7h + 30min + 6s + 153ms; // 2016-05-29 07:30:06.153 UTC zoned_time zt = {"Asia/Tokyo", tp}; cout << zt << '\n';                                          // 2016-05-29 16:30:06.153 JST 

Есть инструменты для работы с международным атомным временем, разбором времён из строки, экзотические типы данных позволяющие хранить даты «вторая пятница февраля», «вторая неделя» или «вторая неделя марта». и т.п.

Так что теперь можно получить дату последней пятницы февраля 4000 года:

auto last_friday_feb = February/Friday[last]; std::cout << 4000 / last_friday_feb << std::endl;

Черновое описание всех возможностей доступно вот тут.

Span

Если вам нравится std::string_view из C++17 (или boost::string_view/boost::string_ref), то std::span вам тем более понравится!

Представьте себе, что у вас есть шаблонная функция, что-то делающая с массивом int:

void do_something(int* p, size_t size);

Чтобы вызвать этот метод нужно достаточно много писать:

std::vector<int> v; do_something(v.data(), v.size());  int data[1024]; do_something(data, std::size(data));  boost::container::small_vector<int, 32> sm; do_something(sm.data(), sm.size());

Другой минус — внутри такого метода неудобно работать с алгоритмами стандартной библиотеки + не будет работать range based for:

void do_something(int* p, size_t size) {     std::sort(p, p + size);     for (size_t i = 0; i < size; ++i) {         p[i] += p[0];     } }

Так вот, std::span — это класс, который хранит указатель и размер массива данных (при том размер порой не хранится, а используется информация, доступная на этапе компиляции). С этим новым классом код становится несколько проще и без указателей:

void do_something(std::span<int> p) {     std2::sort(p);     for (int& v: p) {         v += p[0];     } } // ... std::vector<int> v; do_something(v);  int data[1024]; do_something(data);  boost::container::small_vector<int, 32> sm; do_something(sm); 

Описание std::span доступно в pdf.

typename? Забудьте о нём в C++20!

Если вы путались, когда надо ставить typename, а когда – не надо, то у меня для вас хорошие новости! Начиная с C++20 в подавляющем большинстве мест можно будет не писать typename:

 template<class T> T::R f();  template<class T> struct S {     using Ptr = PtrTraits<T>::Ptr;      T::R f(T::P p) {         return static_cast<T::R>(p);     }      auto g() -> S<T*>::Ptr; };

Новые атрибуты

  • [[no_unique_address]] — если пометите этим аттрибутом переменную класса, то компилятор сможет более агрессивно оптимизировать её расположение в памяти. Например, может в принципе не выделять под неё место.
  • [[likely]] — помечаете им выражение (например `if (flag){ [[likely]] std::cout << «OK»; }` ) или case от switch, и компилятор начинает оптимизировать код, считая, что помеченная ветка будет выполняться чаще, чем другие.
  • [[unlikely]] — подсказывает компилятору, что в это место мы редко попадаем на рантайме.

Сonstexpr метапрограммирование

Внезапная прорывная новость – комитет предварительно одобрил бумагу о использовании std::allocator в constexpr выражениях. Предстоит ещё огромное количество работы, но оптимистичный прогноз – получить к C++20 std::vector и std::string, которые можно использовать в выражениях на этапе компиляции. Это позволит компиляторам лучше оптимизировать, позволит использовать привычные всем контейнеры для рефлексии, метапрограммирования и метаклассов.

Работа в этом направлении продвигается не так быстро, как хотелось бы. Но, тем не менее, на встрече окончательно одобрили бумагу от РГ21 о добавлении «constexpr iterator», что позволит требовать от контейнера итераторов, применимых на этапе компиляции. Другую нашу бумагу на constexpr тему рассмотреть не успели.

Если кто еще не видел рассказ о метаклассах, рефлексии и людях, развивающих эти направления, то рекомендую посмотреть Herb Sutter “Meta: Thoughts on generative C++”.

Новые примитивы для многопоточности и векторных вычислений

Готовится к публикации «Parallelism 2 TS». Самыми интересными вещами, на мой взгляд, является тип данных для SIMD вычислений, благодаря которому можно писать оптимизированный кроссплатформенный код. В зависимости от платформы под капотом будет использоваться различный набор векторых инструкций (SSE, AVX, NEON, MDMX и т.п.):

void compute_on_aligned_data(float* data, size_t N) {     size_t i = 0;     for (; i + native_simd<float>::size() <= N; i += native_simd<float>::size()) {         native_simd<float> v(data + i, vector_aligned);         where(v > 100.f, v) = 100.f + (v - 100.f) * 0.1f;         v.copy_to(data + i, vector_aligned);     }      for (; i < N; ++i) {         float x = data[i];         if (x > 100.f) {             x = 100.f + (x - 100.f) * 0.1f;         }         data[i] = x;     } }

Подробности по SIMD доступны в черновике предложения.

Остальные новинки параллелизма (включая примитивы для fork based параллелизма, новые многопоточные алгоритмы, тип данных для сохранения набора одновременно возникших исключений и т.п.) доступны в черновике.

Прочее

Огромное количество времени комитет занимался обсуждением больших новинок.

Сопрограммы

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

future​<std::string>​ ​concat​(const​ std::string​& ​ prefix​, future​<std::string>​ suffix​) {     co_return ​ (prefix ​ + ​ co_await suffix​); }

Модули

Решали проблемы, возникающие при их имплементации. Упрощали их использование. Ничего прорывного, полёт нормальный.

Reflection TS

Начали формировать новый TS для рефлексии. В основе него пока что находится вот это предложение. Выпущено в свет будет ещё не скоро.

Премия Дрейпера и Оскар

Помимо новостей, напрямую связанных с развитием языка C++, есть ещё новости на смежные темы.

Так Бьёрн Страуструп получил престижную премию Дрейпера за развитие языка C++. На что Бьёрн сказал, что это заслуга всей WG21, и для всех участников закатил банкет.

К другим новостям. О C++ теперь знают актёры Голливуда. При получении Оскара создатель Houdini, популярной программы для графических эффектов, поблагодарил разработчиков языка C++ за C++11.

Вместо итогов

Следующее собрание комитета будет летом. Если вы хотите что-то изменить в C++ или предложить свою идею, то всегда можете написать на https://stdcpp.ru/, где люди из РГ21 помогут вам донести ваши желания до комитета.

Желаете поговорить с нами вживую? Ищите нас на апрельской конференции C++ Russia в Питере.

Хотите пообсуждать C++ с другими разработчиками? К вашим услугам телеграм чат для новичков и чат для матёрых разработчиков, знающих разницу между memory_order_relaxed и memory_order_seq_cst.

Расскажите в комментариях, чего вы больше всего ждёте от C++20 и что из новинок кажется вам наиболее полезным.

FavoriteLoadingДобавить в избранное
Posted in Без рубрики

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *