Из центральной части Канады — на юго-запад США! Альбукерке расположен в штате Нью-Мексико:
На встрече международного комитета по стандартизации C++, которая прошла в этом городе, приняли одно очень большое нововведение в С++20 и несколько маленьких.
operator <=>
В черновик C++20 был добавлен оператор spaceship, с помощью которого можно за одну операцию определять отношение элементов. В простых случаях это значит, что можно определить оператор spaceship и ваш класс научится сравниваться любыми способами: <, >, <=, >=, == и !=. Пример:
Без оператора spaceship | С оператором spaceship |
---|---|
|
|
Поведение оператора можно настраивать типом возвращаемого значения:
class weak_equality;
class strong_equality;
class partial_ordering;
class weak_ordering;
class strong_ordering;
Кроме того, можно писать тело самого оператора, если вам необходимо какое-то особое поведение:
#include <compare> // weak_ordering, is_neq
struct point3d {
int x;
int y;
int z;
std::weak_ordering operator<=>(const point3d& p) const {
using std::abs;
if (auto cmp = abs(z) <=> abs(p.z); std::is_neq(cmp)) return cmp;
if (auto cmp = abs(x) <=> abs(p.x); std::is_neq(cmp)) return cmp;
return abs(x) <=> abs(p.x);
}
};
Описание поведения оператора и примеры использования можно найти в этом документе. Интеграция spaceship со стандартной библиотекой описана здесь*.
Особенно приятно видеть, что добавили следующий алгоритм:
lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, InputIterator2 b2, InputIterator2 e2);
Теперь можно эффективно, в один проход, сравнивать диапазоны данных.
osyncstream
Многие из читателей наверняка писали в std::cout/std::cerr из нескольких потоков одновременно и видели странный вывод:
#include <iostream>
#include <thread>
#include <string_view>
void say_hello(std::string_view username) {
std::cerr << "Hello " << username;
}
void beware_of(std::string_view something) {
std::cerr << something << " is dangerous";
}
int main() {
std::thread t1([]{
say_hello("Rachel");
});
std::thread t2([]{
beware_of("darkness");
});
std::cerr << 'n';
t2.join();
t1.join();
/* Possible output:
Hello darkness
Rachel is dangerous
*/
}
Так вот, в C++20 добавили классы, которые позволяют легко и без лишних накладных расходов избежать перемешивания выводов:
#include <iostream>
#include <thread>
#include <string_view>
void say_hello(std::string_view username) {
std::osyncstream{std::cerr} << "Hello " << username;
}
void beware_of(std::string_view something) {
std::osyncstream(std::cerr) << something << " is dangerous";
}
int main() {
std::thread t1([]{
say_hello("Rachel");
});
std::thread t2([]{
beware_of("darkness");
});
std::cerr << 'n';
t2.join();
t1.join();
}
Подробности — в этой бумаге*.
Заслуги РГ21
Мы, как всегда, ездили на заседание с несколькими предложениями:
- P0539R2 — integers, размер (количество байт) которых задаётся на этапе компиляции. В интерфейсе решили использовать биты, посоветовали разбить бумагу на несколько бумаг поменьше, обсуждали исключения и причие мелочи. Нужно обновлять proposal.
- P0415R0* — constexpr для std::complex. Приняли в C++20 и прямо на месте пометили ещё пару функций как constexpr.
- P0202R2* — constexpr для большинства алгоритмов в <algorithm>. Бумагу разделили на две части и приняли в C++20 ту часть, в которой идёт речь об алгоритмах алгоритмы, не использующих std::swap. Оставшуюся часть примут на следующих заседаниях, будет отдельный proposal.
- P0275R2 — shared_library или классы, необходимые для динамической загрузки библиотек. Рассмотрели в группе Evolution, решили, что бумага затрагивает только стандартную библиотеку и допустимо оставить поведение плагинов не специфицированным. Дальнейшая работа будет происходить в группе Library Evolution на следующих заседаниях.
- P0858R0 (ещё не выложили в открытый доступ) — эту бумагу написали прямо во время встречи в Альбукерке. Бумага позволяет работать с итераторами std::basic_string_view и std::array в constexpr контекстах. На следующем заседании собираются принять в C++20.
Вдобавок нас попросили представить комитету два предложения, непосредственно над написанием которых мы не работали:
- P0457R1 — starts_with и ends_with для строк. Приняли в C++20. Шикарная штука!
- P0458R0 — функция contains(key) member для классов [unordered_]map/set/multimap/multiset. Отправили в LWG, на следующем заседании, возможно, примут в C++20.
Прочие новинки
- range based for теперь может иметь следующий инициализатор:
for (T thing = f(); auto& x : thing.items())
- Отныне можно конструировать лямбды без состояния:
using greater_t = decltype([](auto x, auto y) { return x > y; }); std::map<std::string, int, greater_t> map; constexpr greater_t comparator{}; // OK
- std::is_pod и std::is_pod_v помечены как deprecated.
- Добавили новый type trait std::remove_cvref.
- Атрибут [[nodiscard]] добавили к функциям async(), new, allocate(), empty() и launder().
- std::memory_order* теперь доступны в виде scoped enum.
- Добавили атомарные умные указатели:
template <class T> struct atomic<shared_ptr<T>>; template <class T> struct atomic<weak_ptr<T>>;
- Добавили поддержку чисел с плавающей точкой в std::atomic.
- Множество мелких улучшений и багфиксов.
Параллельно кипела работа по подготовке к Modules TS и были добавлены множественные небольшие улучшения для Networking TS.
Вместо итогов
У вас есть идеи для C++20? Нашли проблемы в C++17, 14 или 11? Просто хотите подстегнуть разработку той или иной фичи C++? Заходите на сайт рабочей группы: stdcpp.ru. Добро пожаловать!
Есть желание помочь с написанием предложений и внести своё имя в историю? Мы подготовили мини-инструкцию по написанию предложений.
27 ноября состоится встреча РГ21, где будет телемост с Гербом Саттером и несколько выступлений. Приходите — вот ссылка на регистрацию. Наконец, готовится встреча C++ User Group в Нижнем Новгороде.
* Во всех этих случаях в стандарт приняли несколько обновлённые версии.
Автор: antoshkka