Хабрахабр

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 и что из новинок кажется вам наиболее полезным.

Теги
Показать больше

Похожие статьи

Кнопка «Наверх»
Закрыть