Ещё один шажок к C++20. Встреча в Альбукерке

в 11:55, , рубрики: atomic, c++, c++ библиотеки, c++17, C++20, c++2a, constexpr, IT-стандарты, modules, networking, operators, Блог компании Яндекс, Компиляторы, Программирование

Из центральной части Канады — на юго-запад США! Альбукерке расположен в штате Нью-Мексико:

Ещё один шажок к C++20. Встреча в Альбукерке - 1

На встрече международного комитета по стандартизации C++, которая прошла в этом городе, приняли одно очень большое нововведение в С++20 и несколько маленьких.

operator <=>

В черновик C++20 был добавлен оператор spaceship, с помощью которого можно за одну операцию определять отношение элементов. В простых случаях это значит, что можно определить оператор spaceship и ваш класс научится сравниваться любыми способами: <, >, <=, >=, == и !=. Пример:

Без оператора spaceship С оператором spaceship
struct point3d {
    int x;
    int y;
    int z;
};

using p_ref = const point3d&;

bool operator==(p_ref a, p_ref b) {
    return a.x == b.x
        && a.y == b.y
        && a.z == b.z
    ;
}
bool operator< (p_ref a, p_ref b) {
    return a.x < b.x
        || (a.x == b.x && a.y < b.y)
        || (a.x == b.x && a.y == b.y
            && a.z < b.z)
    ;
}

bool operator!=(p_ref a, p_ref b) {
    return !(a == b);
}
bool operator<=(p_ref a, p_ref b) {
    return !(b < a);
}
bool operator> (p_ref a, p_ref b) {
    return b < a;
}
bool operator>=(p_ref a, p_ref b) {
    return !(a < b);
}

struct point3d {
    int x;
    int y;
    int z;

    auto operator<=>(const point3d&)
        const = default;
};

Поведение оператора можно настраивать типом возвращаемого значения:

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

Источник

Поделиться

* - обязательные к заполнению поля