Pull to refresh

Comments 99

 Однако его легко реализовать самостоятельно:

можно кратче

constexpr auto filter2 = [](auto filter) {
   return std::views::as_input | std::views::filter(std::move(filter));
};

Да, так ещё легче :) Можно ещё и `inline` добавить

Авторы libstdc++ не любят использовать лямбды в header файлах, это вызывает проблемы при линковке объектов собранных разными компиляторами. Так что в примере использовал максимоально надёжный вариант, вместо самого наглядного

знаю про лямбды и inline, но чтобы не пугать людей вот так сходу лучше написать кратко

И лямбду можно заменить на просто функцию, если не нужно требуемого стандарту эффекта "не искать по adl"

И наконец, мучительная и сложно осознаваемая проблема:

А проблема-то в чём?)

Будет проезд по памяти и Segmentation Fault. Можно попробовать воспользоваться ссылкой и самостоятельно раздебажить неочевидное поведение filter. Добавление std::println в фильтр может помочь.

От ответа теперь только больше вопросов:)

По какой памяти? Что значит "проезд"? Зачем мне вообще ranges, если они такое говно?)

Ну, всякие зипы, слайды удобнее чем руками. В примерах с ренжами при этом, почему-то, всегда что-то примитивное, что без ренжей и удобнее, и сложнее сломать:

auto nb = std::remove_if(coll1.begin(), coll1.end(), std::not_fn(large));
std::vector sub(std::move_iterator(nb), std::move_iterator(coll1.end()));

Хотя тут, конечно, есть нюанс с мувабельностью и известностью размера

я вот уже 6 год наблюдаю за этими ренжами и вот ни как не пойму чего они так вперлись, и с каких ... эти конструкции из пайпов проще и удобнее чем банальный for известный всем и в котором не нужно гадать что где и куда перемещается, копируется и т.д.
По крайней мере во всех примерах которые показывают примеры этих самых ренжей, кроме экономии на 1% строчек в замен на доп. когднитивную нагрузку, я ни чего полезного не вижу. И это если в проект реально много тривиальных хождений по контейнерам.

Они для ленивых вычислений. Примеры на векторах - для краткости, они не показывают преимущества инетервалов.

Оберни циклы в лямбду и получишь ленивые вычисления) Буквально ценой пары скобочек)

Только в отличие от ranges, лямбду можно прикопать в std::function на всякий случай, если хочется. Как прикопать шаблонное месиво, которое плодят ranges - я не знаю)

Ranges решают проблему композиции алгоритмов. Вместо того чтобы городить вложенные циклы или создавать временные контейнеры на каждом шаге, строишь пайплайн ленивых вычислений, а это плюс жизнь производительности потому что данные обрабатываются за один проход, но ценой читаемости

Но... Всё тоже самое можно сделать просто на композиции функций)


Curves toCurves(const QPainterPath& pPath) {
    using QPP = QPainterPath;
    using El = QPP::Element;
    Curves curves;
    for(auto&& elements: v::iota(0, pPath.elementCount())
            | v::transform(std::bind(&QPP::elementAt, pPath, _1))            // to Element
            | v::chunk_by(+[](const El&, const El& r) { return r.type; })) { // to Subpath Polygons

        // qInfo() << "elements" << elements.size();                         // count of elements

        constexpr auto splitPaths = +[](const El&, const El& r) { return r.type > QPP::CurveToElement; };
        auto subpaths = v::chunk_by(elements, splitPaths); // separate Curves

        Curve curve;
        for(auto&& [from, to]: v::pairwise(subpaths)) { // 'from' point to bezier Point in 'to' if
            if(curve.empty()) curve.emplace_back(static_cast<QPointF>(from.front()));

            if(to.front().type == QPP::CurveToElement) { // is arcTo
                // Проверка, является ли кривая Безье дугой окружности
                QPointF center;
                double radius;
                if(isArcOfCircle(from.back(), to[0], to[1], to[2], center, radius, 5e-3)) {
                    // qInfo() << "Arc 1" << radius << center;
                    curve.emplace_back(static_cast<QPointF>(to.back()), center, DIR(from.back(), center, to.back()));
                } else {                          // is lineTo
                    drawCross45(center, Qt::red); // debug
                    curve.emplace_back(static_cast<QPointF>(to.back()));
                }
            } else
                curve.emplace_back(static_cast<QPointF>(to.front()));
        }
        if(curve.size()) curves.emplace_back(std::move(curve));
    }
    return curves;
}

Проще и безопаснее написать обычный for с if внутри. Да, не так модно и не в одну строчку, зато код будет читать даже джун, а не только три с половиной человека из комитета по стандартизации

Зачем городить еще одну конструкцию std::views::safe_filter, если можно было бы просто изменить реализацию std::views::filter?

Это бы сломало пользовательский код в валидных местах использования, например:

  auto sub = coll1 | std::views::filter(large)
                   | std::views::reverse
                   | std::ranges::to<std::vector>();

Как это вяжется с:

Теперь общая рекомендация от комитета такова: по умолчанию перед фильтром всегда использовать std::views::as_input |. Такая конструкция уберёт лишнее кэширование из фильтра, заставит его быть гарантированно однопроходным и в целом работать без сюрпризов

Т.е. рекомендуется по умолчанию использовать, но при этом оно в каких-то случаях что-то гарантированно сломает?

Всё так. Рекомендуется по умолчанию использовать. Если вдруг код, с использованием аналогов safe_filter не собирается, то надо задуматься над тем, что происходит и обратить на код внимание. Если всё ещё не понятно, почему не собирается - то не стоит писать код, который вы не понимаете стоит код упростить. Если же вам всё понятно и нужен именно небезопасный фильтр - используйте его.

А, под ломается имеется ввиду поломка сборки...

Хм. Т.е. переименовать кучу вещей и поменять возвращаемые значения некоторых функций – это сборку не ломает, и ОК, а здесь возможно что-то сломается, и уже нельзя.

Комитет случайно не завел std::committee_bool, где можно хранить его решения?

Менялись имена вещей, которые повились только в C++26. Так как стандарт ещё не вышел, а все реализации помечают новинки как "экспериментальные" - то менять названия ОК.

Не ОК менять названия вещей, которые уже длительное время в стандарте (например добавились пару стандартов назад)

Чел из Яндекса не осилил привести пример из нововведения по линейной алгебре

Комитет C++ собирается в Кройдоне, чтобы решить, как переименовать sat_ в saturation_. От этих решений зависит судьба высокопроизводительных вычислений во всем мире. Запомните этот коммент

Поддержку корутин в std завезут? Работу с сетью?

Сеть отложили в очередной раз, так что самое раннее в C++29 её увидим.

Корутины уже были добавлены в C++20, в C++23 приняли std::generator. В C++26 появляется `std::execution::task`. Или вы больше ждали какие-то другие примитивы?

На счет сети, ее планируют делать на базе std::execution или будет включен в стандарт boost::asio?

Boost.Asio уже работает с executors. Так что ответ "да" на оба вопроса

Сеть разве не передумали добавлять в этот язык? Читал стать, што это невозможно, т.к. у сетей слишком разная реализацыя и не стандартизировать, а также обожглись на низкой производительности regex. Т.е. сторонние regex производительнее добавленной стандартной и это признано неудачей.

Пожалуйста хватит тащить в стд функционал которому место в пользовательских библиотеках, не надо взваливать на и так перегруженных разрабочиков компиляторов труд под реализации фич требующих серьезных domain spacific знаний. Есть asio для сети, blas для линала и люди которые их делают явно больше заинтересованы и обладают большей экспертизой для поддержки данных либ

а в рефлексию по итогу без изменений зашли пользовательские аттрибуты? Где-то раньше видел прототипы кода.

Да, они в C++26 под именем "аннотации". Синтаксис у них похож на аттрибуты [[=any_compile_time_object]]

Опережающее описание для вложенных классов в каком веке появится?

class Foo::Inner; // ошибка

Как только вы реализуете прототип в компиляторе и напишите proposal. Дальше будет процесс обсуждения и по итогу, есть все шансы увидеть новинку в ближайшем стандарте

Есть предложение на C++29 добавить в стандартную библиотеку следующую функцию:

void EarnBillionDollars ( time_point deadline, long long bankaccount );

Undefined behavior не допускается.

Какая короткая статья... А что там из линейной алгебры?

В C++26 добавили функции для работы с векторами и матрицами (да-да! BLAS и немного LAPACK). Более того — новые функции работают с ExeсutionPolicy, так что можно заниматься многопоточными вычислениями функций линейной алгебры. Вся эта радость работает с std::mdspan и std::submdspan.

В целом формат статьи - "новости с последней встречи ISO". Если хочется полный обзор C++26, то надо прочитать соответствующие статьи за последние 3 года - получится весьма подробно по всем темам.

Спасибо. То есть, плотные векторы и матрицы в стандарте, уже неплохо.

превратили плюсы в полигон для гиков.

А что именно вы бы хотели изменить в C++?

  • Добавить сеть

  • Добавить приличные парсеры популярных текстовых форматов

  • Выкинуть всё говно, которое наворотили со строками и сделать по-человечески. Заколебало везде за собой таскать ICU.

  • Запретить устаревший синтаксис (хоть те же "эпохи" ввести)

  • Стандартизировать ABI

  • Хочется стандартный пакетный менеджер

  • Интрузивные контейнеры

  • Стандартизировать отключение исключений

Но в целом, С++ уже ничего не поможет) Он слишком многословный и хрупкий) Его придётся любить таким, какой он есть

Не нужно сеть, не нужны парсеры, это вещи пользовательского домена.

ABI и удаление говна правда хочется, но никогда не случится, нужен форк плюсов по сути.

Пакетных менеджеров хоть попой жуй, выбирай который нравится, не надо ничего стандартизировать, оставь рынку решить проблему не прибегая к твердой руке

Не нужно сеть, не нужны парсеры, это вещи пользовательского домена.

Именно поэтому они есть в стандартной библиотеке... Вообще любого языка?)

Пакетных менеджеров хоть попой жуй

Пакетный менеджер один другого хуже) Хотя практически любой современный язык идёт комплектом с тулингом. "Жопой жуй" - это самый плохой сценарий. Это значит, что при смене места работы, заново учить очередные сборочные костыли. А это значит, что при необходимости добавить библиотеку снова придется приседать, склеивая ежа с ужом. Надоело.

Впрочем, зная комитет - соглашусь. Им такую задачу доверять нельзя. Сделают говно.

оставь рынку решить

С++ уже сколько лет? Ну даже если отсчитывать от первого стандарта - уже 28 лет. Нихрена рынок не может, это мы уже поняли)

Давно стоит переписать "с учетом опыта", назвать E++ (D занято могильным камнем))и не тащить я язык то что обычно лежит в либах?

Первое неплохо, а второе проблемно произнести :)

Изкоробочные сборщик, файл проектов и пекедж менеждер. В C# все это есть, например.

Сборщик мусора? :)

"Если бы в C++ был сборщик мусора, то он бы просто удалял весь код, на нём написанный", но тем не менее...

Что я бы хотел в с++ изменить?

  1. Ну наверное сперва нужно разогнать комитет по стандартизации или как там его.

  2. Очистить язык от всей той немыслимой шелухи, которую налепил этот безумный гик-комитет.

  3. Оставить в стандартном ядре языка фичи, которые реально полезны и сокращают ритуальные телодвижения - constexpr, auto, templates, lambdas, move semantics, smart pointers, threads, locks, std: structures, collections, algos, streams, variants, tuples, etc. Ну разумеется, маст хэв, изначальные фишки плюсов - namespacees, classes, virtual functions, heap allocations etc. Нативная работа с Юникодом и UTF8 - of course must have.

  4. Всю остальную гиковскую и псевдо инновационную оверинж чушь: rtti, exceptions, concepts, conditional template instantiations, etc - выпилить в какие нибудь опциональные стандартные и нестандартные расширения - для маньяков - c++ maniac extensions.

  5. Ну либы и рантаймы - тут все понятно - это не язык, а литература.

  6. Перестать беспокоиться о криворуких говнокодерах. Не умеют в nullptr, delete, array index out of bounds, etc - пускай на Бейсике пишут.

  7. Не париться о backward compatibility - всегда можно компилить и билдить с нужными версиями.

  8. В общем, не впихивать в более менее стабильное ядро языка лишние протоны и нейтроны - не превращать излишней мишурой чистое золото гения Страуструпа в тяжелые и нестабильные изотопы технеция.

Перестать беспокоиться о криворуких говнокодерах. Не умеют в nullptr, delete, array index out of bounds, etc - пускай на Бейсике пишут

То есть, RAII тоже выпилить, заодно со smart pointers? ;-)

В общем, не впихивать в более менее стабильное ядро языка лишние протоны и нейтроны

Вроде под Ваши требования подходит C++11/14. Можно в опциях компилятора включить ограничение, что он не поддерживает всё, что новее (C++17 и далее) - profit?

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

Выкинуть... чушь: rtti, exceptions, concepts, conditional template instantiations

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

Комитет принимает 1 пропосал из десятка.

У каждого свои представления о гармонии. Комитет руководствуется тем, чем люди пользуются, и в чем испытывают потребность. Возможно, это выглядит тупым с чьей-то точки зрения, но у каждого есть возможность самостоятельного выбора - пользоваться этим или нет.

Ну так очевиден же стратегический выбор индустрии и разумных правительств. И он же не в пользу плюсов.

Так что эти ваши апологетские мантры не работают так, как вам бы хотелось.

В стандарт должно естественным эволюционным образом входить то, что проверено годами позитивной практики, например, как это было в бустах, а не эти все абстрактные лихорадочно придуманные и наспех прикрученные противокостыльные антикостыли.

Каждый раз радуюсь что ушел с этого языка. Все эти симпозиумы выглядят как поиски в болоте костылей для костылей чтобы поддерживать костыли

Вы просто не читаете аналогичные отчёты по другим языкам программирования ;-) А соответственно не знаете о проблемных местах других языков программирования и о том, какие пути обхода проблем используются там

Я как-то в упор не понял, смотрел на примеры с фильтрами. Написано более менее понятно, однако: там неопределенное поведение, там ошибки по памяти, там куча других проблем... И вместо того чтобы исправить само поведение (а все намекает на это), мы добавляем новую конструкцию std::views::as_input. Это же так очевидно! И все будут знать и помнить, и главное понимать что она делает.

И исправить ничего нельзя ведь это сломает будущую обратную совместимость , по этому пусть будет не внятное , а через три года сделаем фикс в виде нового safe-filter . Какая то бюрократия ради бюрократии

будущую обратную совместимость

filter уже 6 лет с нами, аж с C++20

А дальше тонкий вопрос - хотите ли сломать ~20% использований чтобы обнаружить 0.1%-1% UB? Комитет выбрал так не делать и идти по пути safe_filter

Главное, чтобы потом не пришлось писать safer_filter и safest_filter.

Компиляторы и так уже имеют флаги, в каком стандарте компилировать код. Почему нельзя смотреть на них и выбирать поведение, соответствующее версии стандарта (да, так ненавидимые(?) комитетом редакции)? Комон, всякие линтеры/миграторы при переходе со стандарта на стандарт это уже реальность, данная нам в ощущениях, зачем пытаться делать вид, что ее нет?

Почему нельзя смотреть на них и выбирать поведение, соответствующее версии стандарта

В случае перехода от filter к поведению safe_filter меняется тип диапазана с BidirectionalRange/ForwardRange на InputRange. Другими словами, некоторые валидные pipeline обработки просто перестают компилироваться. Как предлагаете обойти эту проблему, чтобы не сломать валидный пользовательский код?

Разве InputRange не является более общим, чем ForwardRange? Т.е. safe_filter принимает более широкий тип аргументов, чем filter, как это сломает существующие использования (разве что кто-то использовал SFINAE, ну так теперь оно же концептами заменено?)? И разве возвращаемый тип не является таким же, как принимаемый? Если кто-то передавал ForwardRange, то и получать назад будет ForwardRange.

С точностью до наоборот - если InputRange - то можно только инкрементить и один раз разадрессовывать. А значит отваливаются все те ranges, которые требуют на вход Forward/Bidirectional

Так что же тут наоборот-то? Forward является Input который является InputOutput, если я правильно понимаю, что написано в

Следовательно, все, что принимает Input, может принять Forward. Если раньше мы принимали только Forward, то теперь принимаем как Forward, так и Input. Почему это должно ломать клиентов, которые передавали Forward?

(повторюсь, я предполагаю, что filter возвращает тот же тип, что и принимает. К сожалению, понять, что возвращает эта функция, невозможно, поскольку вроде это и не функция вовсе, а класс, как показано в https://en.cppreference.com/w/cpp/ranges/filter_view.html)

Есть концепты, которым могут удовлетворять разные диапазоны. Так например для Input концепта требуется наличие двух операторов ++ и одного оператора *. Для Bidirectional концепта необходимо ещё и наличие операторов --.

`view` принимают диапазон на вход и выдают диапазон. `view` реализуют алгоритм, и некоторые алгоритмы требуют для своей эффективной реализации удовлетворения более требовательного концепта на вход. Так например std::views::reverse требуется Bidirectional диапазон, так как надо идти по диапазону в обратном порядке и нужено оператор--.

Так вот, filter возвращает Bidirectional диапазон, если ему на вход пришёл Bidirectional диапазон, за счёт чего скомпилируется идущий за ним std::views::reverse.

safe_filter всегда возвращает Input, с которым не может работать std::views::reverse так как у такого диапазона нет оператора --.

safe_filter всегда возвращает Input

А почему? Почему filter может вернуть входящий тип, а safe_filter не может? Это результат наколеночного исправления путем приписывания as_input | или какое-то фундаментальное ограничение?

Фундаментальное ограничение. Если возвращать не Input диапазон, то как раз вылезают все проблемы с тем, что можно несколько раз проходить по диапазону, значение может измениться после первой фильтрации и новая фильтрация приводит к непредсказуемым последствиям (UB)

А кто-то может понятным языком объяснить проблему с фильтрами?

Про то, чтобы запрашивать у компилятора максимальный размер стека функции - да, компилятор, возможно, что-то ответит. Но, увы, этот ответ не будет универсальным.

Практический пример - вы узнали размер в compile time, ок.
А потом собранное приложение запускаете, внезапно, через qemu на другой архитектуре. Например, бинарь amd64 запускаете на arm64. И там, внезапно, размер стека оказывается другим; не тем, который подсказал компилятор. Особенно заметна разница при "холодном" запуске функции. Эмулятор что-то там делает - возможно, транспилирует код под актуальную архитектуру - и этот шаг кушает стек.

Эм, так ведь то, что вы запускаете бинарь через Qemu на какой-то левой архитектуре вовсе не проблема и не зона ответственности компилятора, формировавшего бинарь. Это явно проблема и зона ответственности любознательного экспериментатора.

Осталось пройти формальные этапы в вышестоящих инстанциях ISO, и мы получим C++26 который заслужили.

и еще лет 6 чтобы это все начали поддерживать компиляторы переносимо
Сеть возможно увидим не раньше С++29, но в озвученных планах по сети ничего...

и еще лет 6 чтобы это все начали поддерживать компиляторы переносимо

В этот раз с поддержкой всё уже очень не плохо. GCC-16 поддерживает как рефлексию, так и контракты. Clang тоже с рефлексией неплохо справляется

Думаю C++26 очень оперативно поддержат (в этом стандарте нет C++20-модуле-подобных новинок, затрагивающих системы сборки, тулчейны и вообще всё)

Вопрос скорее всего не совсем именно про эту встречу (поскольку она была, как я понимаю, по тематике именно C++26), но интересно, почему никак не упоминается пачка пропозалов на добавление в STL графов (P3126-P3131). Есть ли перспективы попадания этих нововведений в C++29? Как прошли последние обсуждения этих предложений (на предыдущей встрече комитета, или раньше)?

Оба предложения обсуждались несколько раз. Пока оптимистично планируется их приземлить в C++29

Если вы заинтересованы в этих предложениях, то кажется самое простое что можно сделать - воспользоваться https://github.com/stdgraph на основе которого строятся данные нововведения в стандарт C++ и зарепортить авторам библиотеки фидбек

Спасибо большое, поправил

P.S.: хабр рекомендует об опечатках сообщать напрямую в личку автору

Я люблю С++, но он как-то незаметно из отличного прикладного языка превратился в brainfuck.
И плохо тут не то, что что-то копошатся, делают, а то, что на инструментарии для создания _исключительно_ библиотек, незамутненные программисты пытаются писать этот самый прикладной код.

А что по вашему мнению помогло бы исправить ситуацию? Какие дополнения к стандарту?

Этот вопрос звучит как шутка или даже издевательство: "давайте еще навернем и люди потянутся".
Рыба с головы гниёт, и именно ней что-то надо делать. Но я почему-то думаю, что голова отваливаться не собирается, а повреждения уже необратимы.

Из вашего первого комментария не совсем ясно, что именно плохо:

  • то, во что язык превратился (имеется в виду совокупность фич, описанная в стандарте);

  • то, что на языке разрабатывают прикладной софт, а не только библиотеки.

Либо эти два фактора сразу.

Во что превратился - плохо безусловно. По пальцам одной руки можно пересчитать действительно полезное добавленное за последние лет 10. А грязь в языке можно бочками черпать.

Но что хуже, я эту грязь я иногда вижу в прикладном коде, потому что люди читают новые стандарты и от скуки(?) пишут так, что сами через полгода не поймут, что и зачем. А уж как этот код отлаживать удобно..

По пальцам одной руки можно пересчитать действительно полезное добавленное за последние лет 10.

Я плохо знаю плюсы, особенно современные, но у меня противоположное впечатление – не так уж много из добавленных за последние 10 лет фич, которые не нравятся мне или кажутся мне бесполезными.

В конце концов, не могут все нововведённые фичи быть полезными и нужными абсолютно всем. Вспоминается, как был здесь один где-то с год назад, который пытался утверждать, что auto - зло, и всегда типы нужно писать явно. Даже пару статей опубликовал с подобными утверждениями, которые неслабо заминусовали.

Меня всегда интересовал вопрос: Чем руководствовались писатели стандарта C++, когда писали про common sequence initialization для union? Кому могла прийти в голову мысль, что другие члены объединения могут быть проинициализированы только в том случае, если их компоновка в точности совпадает с компоновкой самого длинного, инициализируемого напрямую члена? При том, что эти люди прекрасно осведомлены о применении union множеством библиотек в runtime для конвертации представлений чисел бит в бит! Почему нельзя было оговорить тоже самое для constexpr, параллельно устранив сложности реализации того, что понаписано в стандарте?

Антон, может вы сможете мне это пояснить?

В C нет такого же понятия "объекта", как в C++. Соответственно в C можно спокойно написать в одно поле union, прочитать из другого, и это будут просто байтики. А в C++ стандарт оперирует объектами и их временами жизни. Это позволяет делать некоторые хитрые оптимизации (которые пока редко включают компиляторы по умолчанию, как раз из-за того что сломается C код)...

Вот и получается два противоречивых требования - хочется и совместимость с C, и хочется новые оптимизации. Балансирование между этими двумя желаниями приводит к решениям, на подобие common sequence initialization

Но ведь “объект” в C++, согласно стандарту, это лишь экземпляр любого типа, включая фундаментальные, пришедшие из Си, а на первых страницах стандарта написано, что Си является подмножеством C++, со всеми вытекающими (хоть и с некоторыми ограничениями).

Я понимаю, что ООП и перегрузка операторов позволяют изменять поведение объекта, но как это может сказываться на “конвертации” бит в бит? Почему нельзя отдать это на откуп разработчику, по принципу “сам накосячил — сам дурак”? Какой тайный смысл во всех этих искусственных ограничениях?

C++32 же, или почему отложат на год?

Правильно ли я понял, што simd откладываетса до C++29?

Да, я это читал, но почему на cppreference почти всё красное-неготовое? А насчёт второй ссылки - я так понял, што новое может появлятса постепенно, быть экспериментальным, включатса через настройки компилятра.

И одна нейросеть пишет, што simd должна появитса в 26, другая "На текущий момент (2025-2026 гг.) уже доступна в виде std::experimental::simd ", "Ожидается, что этот стандарт будет принят рынком быстрее предыдущих из-за высокой востребованности производительности."

Видимо, пока не обновили свои базы.

Т.е. я не нашёл окончательново подтверждения или не знаю где смотреть.

О, вот здесь нашёл подтверждение: https://www.opennet.ru/opennews/art.shtml?num=65102

simd будет в C++26. В GCC-16 уже будет готовая к использованию реализация, а до этого была в GCC реализация std::experimental::simd, на основе которой как раз и принимали std::simd

 почему на cppreference почти всё красное-неготовое?

cppreference тоже не мгновенно обновляется.

cppreference некоторое время был на последнем издыхании в режиме read-only.

Второе дыхание он, к счастью, обретает вот прямо сейчас.

Sign up to leave a comment.

Information

Website
www.ya.ru
Registered
Founded
Employees
over 10,000 employees
Location
Россия