company_banner

C++20 укомплектован, C++23 начат. Итоги встречи в Кёльне

    На днях прошла встреча международного комитета по стандартизации C++ в Кёльне. В прошлый раз был принят feature freeze на C++20, так что комитет должен был обсуждать только исправления уже принятых вещей, а добавлять новинки уже в C++23…

    … но всё было не так!



    Что сделали с std::flat_map; останутся ли страшные ключевые слова co_return, co_await и co_yield; успели ли доделать std::format; в каком виде будут контракты в C++20? Всё это вас ждёт под катом.

    Evolution Working Group


    Понедельник


    День был насыщенным — решили переименовать все концепты в snake_case вместо CamelCase. Вдобавок с большим перевесом по голосам приняли предложение P1607, которое меняет синтаксис и поведение контрактов на более понятное (но также требующее макросов).

    Вторник


    Обсуждали корутины. Отклонили всё, включая наше предложение на отбрасывание co_ с ключевых слов для корутин. Увы.

    Среда


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

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

    Четверг, пятница


    Обсуждали вещи для C++23. Основные силы были сосредоточены на новых механизмах в обработке ошибок. Были как общие размышления на тему, так и конкретные предложения на новый спецификатор исключений throws.

    Library Working Group


    В комитете есть подгруппа LWG. Любой документ, добавляющий функциональность в стандартную библиотеку, должен пройти ревью в этой подгруппе.

    Средняя пропускная способность LWG — ~30 документов в неделю. В Кёльне надо было рассмотреть более 50 документов, среди которых около половины крайне внушительных размеров, например:
    * std::flat_map
    * std::jthread
    * operator<=> для стандартной библиотеки
    * Новые примитивы синхронизации
    + из EWG прилетела бумага на переименование концептов в snake_case.

    Что из ранее одобренного успели дотащить до C++20



    Увы, std::stacktrace, std::flat_map, std::flat_set в C++20 не попали :(

    С++23


    Началась работа над крупными вещами, включая адаптацию Boost.Process для стандарта, переосмысливание работы с файлами и вводом/выводом, линейную алгебру, юникод, 2d графика, аудио, JIT компиляцию C++ кода.

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

    Заслуги РГ21


    Как и всегда, мы работали в различных подгруппах, чинили баги, правили тексты, делились опытом по внедрению, презентовали бумаги, авторы которых не смогли приехать. Так, например, в последний момент заметили и подправили работу std::format с Inf/NaN; убрали неожиданности из интерфейса jthread; протащили через одну из подгрупп предложение на хеширование pair, tuple, string, array.

    Много времени провели в подгруппе SG1 Concurrency за обсуждением concurrent_unordered_map. В итоге функции visit теперь не будут защищать переданный value от конкурентной модификации, только от удаления из контейнера:

    concurrent_unordered_map<int, std::string> conc_map;
    conc_map.visit(42, [](std::string& value) { // да, неконстантная ссылка....
        // Раньше было всегда OK. Теперь OK если другие визиторы не меняют это же value.
        std::cerr << value; 
    
        // Раньше было всегда OK. Теперь OK если другие визиторы не меняют это же value.
        value += "Hello"; 
    });
    .
    С таким интерфейсом проще стрелять себе в ноги выжать максимум производительности для некоторых статистических задач, при этом синхронизация фактически ложится на плечи пользователя:

    concurrent_unordered_map<int, std::atomic<int>> conc_map;
    conc_map.visit(42, [](std::atomic<int>& value) { // да, неконстантная ссылка....
        // Всегда OK
        ++ value; 
    });

    Также есть небольшие подвижки в SG6 Numerics — начали думать над Numerics TS с большим количеством новых классов чисел, в том числе с wide_integer от нас.

    Прочее


    Осенью в Питере состоится конференция C++ Piter, на которой можно будет лично пообщаться со многими людьми из комитета.

    Встреча РГ21 по итогам Кёльнского собрания ISO состоится 9 августа (регистрация обязательна, количество мест ограничено). На встрече можно задать вопросы об интересующих вас новинках и узнать побольше о C++20 и C++23.

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

    Контракты…

    Яндекс
    469,99
    Как мы делаем Яндекс
    Поделиться публикацией

    Комментарии 348

      +3
      + из EWG прилетела бумага на переименование контрактов в snake_case.

      but why?

      operator != теперь по умолчанию генерируется из operator ==. Лишние операторы были выкинуты из стандартной библиотеки, некоторые были заменены на operator <=>

      а это никакие optional&ltfloat&gt{NAN} не поломает?
        0
        Концепты решили переименовать в snake_case, чтобы случайно не пострадали те кодове базы, которые пишут using namespace std; и используют CamelCase наименование для собственных классов. А вообще мне тоже кажется, что CamelCase в этом месте смотрелся лучше.

        optional&ltfloat&gt{NAN} поломать не должно. operator != по прежнему можно писать, и в этом случае будет использовать самописный, вместо автогенерённого.
          +5

          Я так понимаю, что под CamelCase имеется ввиду PascalCase?

            +5
            Теперь случайно пострадают те безумцы, которые пишут using namespace std; и используют snake_case для собственных классов :)
            +6
            but why?
            В стандартной библиотеке всё в snake_case. Было странно, что какая-то часть выбивалась из этого правила.
            +8

            Да хрен с ними с контрактами, главное концепты оставили)


            Расстроен на счет co_рутин. Что у них там вообще на уме? Теперь С++ стал еще страшнее)


            Не понял за каким понадобились asm в constexpr?


            Ничего не упомянули про templated lambda


            Интересно, как работает внутри constexpr вектор)


            Шел 2019й и НАКОНЕЦ завезли человеческое форматирование строк. Так гляди еще и ICU затащат.


            В общем, приеду на конфу, закидаю вопросами)

              +3
              > Не понял за каким понадобились asm в constexpr?

              В основном понадобилось для ассемблерно соптимизированных алгоритмов и классов:
              constexpr pow(int x, int y) {
                  if (std::is_constant_evaluated()) {
                      // Мы в constexpr
                      --y;
                      while (y--) x*=x;
                      return x;
                  } else {
                      // runtime вычисления
              
                      // не собиралось до недавнего времени:
                      __asm__("pow eax, edx\nret"); // ассемблерный псевдокод
                  }
              }


              > Ничего не упомянули про templated lambda

              Это уже давно добавили. В этой статье только новинки последнего заседания.

              > Интересно, как работает внутри constexpr вектор)

              Компилятор запоминает тип объекта при вызове placement new и внимательно следит за его жизнью, прерывая компиляцию при любом UB.

              А вообще constexpr new пока что реализован в одном единственном компиляторе EDG, и то в developer preview.

              > В общем, приеду на конфу, закидаю вопросами)

              С радостью на них отвечу!)
              +2
              Я кажется немного заблудился во всех изменениях стандартов. Подскажите пожалуйста — какая судьба у Networking TS? Оно куда нибудь в итоге попало?
                +3
                Оно в лучшем случае попадёт в C++23. Но перед этим в C++23 должны попасть Executors, а они пока не готовы.
                  +2

                  Насколько я помню из статьи про Feature Freeze, а С++20 это не попадает и потенциально переезжает в С++23

                  0
                  У вас в тексте касательно using enum несколько ошибок: KRed с большой буквы, using enum rgba_channel внутри свитча, переменная my_channel не существует.
                    0
                    Спасибо, поправил
                      0
                      Там в оригинальном тексте по ссылке такая же ошибка. 6.2. Switching with no syntax overhead
                      +11

                      Господи, дождались! В С++20 будет число пи :)

                        +2
                        Меня больше завораживают констаны «квадратный корень из 3» и «квадратный корень из 2» :)

                        А вообще жаль что не успели принять constexpr for cmath and cstdlib. На мой взгляд второе — несколько полезнее.
                          +2

                          Насчет корня из трех не знаю, но корень из двух попадается в формулах очень часто.
                          Мне больше интересно, как вся математика до сих пор жила без числа "пи", в С++11 же кучу тригонометрии и распределений насовали.

                            +2
                            А вот так и жили. M_PI в math.h на всех распространённых платформах есть, а что в стандарте нет — ну кого это волнует.
                              +10
                              const float pi = 3.14f; //И так сойдёт

                              Как-то так
                                0
                                Поделитесь пожалуйста, что было не так с PI?
                                  0
                                  А ничего не было. В стандарте его как бы нету, но в POSIX — оно как бы есть. Ну и Microsoft его себе подобрал тоже.

                                  А что, в реальности-то, осталось, что не POSIX и не Windows?
                                    0
                                    Embedded с их огромным количеством не POSIX операционок (и отсутствием операционок), всякие ОС которые POSIX только на словах.
                                      0
                                      Так там и с поддержкой стандартной библиотеки… так себе.

                                      Формально да — замечание верное, а практически — наличие M_PI ничуть не менее вероятно, чем какой-то фичи из стандарта…
                                        +2
                                        Поэтому сейчас усиленно идёт работа над freestanding — выделением части стандартной библиотеки, которая должна работать на любом утюге. Работа идёт в паралель, так что новинки добавлять никто не запрещает.
                                        +1
                                        Эмбеддер, который операционку свою написал, и число пи откуда-нибудь да скопипастит.
                                        Вот битовые операции наконец-то привезли! Можно перестать строить свои велосипеды (лет через N-цать, в эмбед-компиляторах не сразу новые фишки появляются).
                                        Ой. Прочитал пропозал. Вашу ж мать, а где «перевернуть биты в байте», «перевернуть байты в инте» и прочие стандартные htonl()?
                                          +1
                                          Это в отдельных предложениях, например в wg21.link/P1272R2
                                            0
                                            Вашу ж мать, а где «перевернуть биты в байте»

                                            а где «перевернуть биты в байте» в процессорах?
                                              0
                                              Вот тут, например:
                                              infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/BABJJDDB.html

                                              То, что в большинстве «больших» процессоров это придётся делать программно… Ну, прикладному программисту эти подробности в 99.9% случаев неинтересны.
                                              Тем более, есть более интересные реализации, чем наивный цикл по 32-м битам.
                                                0
                                                Тем более, есть более интересные реализации, чем наивный цикл по 32-м битам.

                                                да да, 25 инструкций для разворота 32 бит. Мне даже доводилось считать их в sse ибо так получалось заметно шустрее
                                      +2

                                      Не, как обычные пользователи жили — понятно, а вот как без числа пи жили всякие std::sph_bessel или std::cauchy_distribution (всмысле, сам библиотечный код), если там в исходной формуле число пи?
                                      Неужели тоже константу заводили каждый раз?

                                        +4
                                        Не заводили. Прям так писали:
                                            // purposefully let tan arg get as close to pi/2 as it wants,
                                            // tan will return a finite
                                            return __p.a() + __p.b() *
                                                _VSTD::tan(3.1415926535897932384626433832795 * __gen(__g));
                                        
                                          +3

                                          Капец.

                                          0

                                          Если стандарт определяет функцию acos(x), то почему бы просто не написать pi = acos(1)?

                                            0

                                            Самому написать? Или библиотеке?

                                        +2
                                        Один, довольно костыльный и, как мне кажется, медленный метод — acos(-1)
                                          0

                                          Говорят, 4*atan(1) точнее выходит :)

                                            +2
                                            Небось умный компилятор заменял это выражение сразу на число.
                                              0
                                              А если не заменял, то это можно сразу репортить как missed optimization :)
                                                0
                                                Так и есть
                                                int f()
                                                {
                                                return std::acos(-1);
                                                }
                                                mov eax, 3
                                                ret
                                              0
                                              Корень из трех — это ж тангенс угла в 60 градусов :)
                                          +1

                                          А битовые операции обещают константность выполнения для избегания атак по времени или оно в таком виде не рассматривается?

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

                                            Так что битовые операции, и любые другие операции, не дают никаких гарантий по времени выполнения.
                                              0

                                              Так оно с законами никак не коррелирует. Это все требованя к реализации, как скажем ожидание, что доступа к элементам массива будет за O(1) времени. Так и тут. Хотя это все вероятно implementation/platform/architecture specific и криптобезопасный код будет как и раньше на чистых битовых операциях.

                                            +4
                                            После длительного обсуждения решили, что контракты в принципе не готовы к C++20. И убрали их из стандарта.

                                            Гм. Мне одному видится отсутствие логики в принятии этого решения?


                                            Впрочем вам конечно виднее...

                                              +1
                                              Внезапно осознали, что при написании библиотек скорее всего придётся разработчикам вводить свои макросы для контрактов. Поэтому поменяли старый дизайн на такой дизайн, который проще, но всегда требует макросов.

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

                                              Скорее всего контракты вернутся в C++23.
                                                0
                                                Контракты уже были реализованы в каком либо компиляторе?
                                                  +1
                                                  В GCC, в отдельной ветке. Поиграться можно например на godbolt, на компиляторе gcc (contracts)
                                                    0
                                                    Я с вот этой веткой CLang игралсся:
                                                    github.com/arcosuc3m/clang-contracts
                                                    Делал на работе по ней презентацию с примерами, если честно, никому текущая реализация не понравилась. Очень много неочевидных моментов.
                                                    Так что я как только прочитал, что контракты выкидывают — прямо вздох облегчения :)
                                              +3
                                              С++23

                                              Началась работа над крупными вещами, включая… юникод


                                              2019 год на дворе. Но хотя бы началась…
                                                0
                                                … но при этом до сих никто не знает как сделать эффективную поддержку юникода в C++.

                                                Или знают но молчат :) Предложений на юникод не было с 2000. Стали появляться лишь в последние несколько лет.
                                                  +1
                                                  > при этом до сих никто не знает как сделать эффективную поддержку юникода в C++.

                                                  Сделали бы хотя бы неэффективную, ведь есть же ICU — бери и срисовывай
                                                    +3
                                                    Ага. А потом инсталлируй 60 библиотек по 40 мегабайт каждая.

                                                    Отличная, блин, идея. ICU — это пример того как не надо делать.
                                                      +2
                                                      Я совсем не против, если сделают лучше ICU. Но только при условии что если не я, то хоть дети мои доживут.

                                                      Как по мне, мы здесь столкнулись с классическим примером прокрастинации, когда авторы стандарта делают не то что надо людям, а то что им хочется и интересно.
                                                        +6
                                                        Как говорил Юсутис «Это ваша вина!».

                                                        Авторы стандарта — это обычные люди, которые просто написали предложение по улучшению языка. Так что если вам нужен юникод, а вы ничего не делали — «Это ваша вина!».
                                                          –2
                                                          По-моему всё уже давно сделано в ICU. Если что-то не нравится — код открыт.
                                                            0
                                                            В ICU нет главного: стабильного API. И нет ни одного желающего его поддерживать, только желающие пользовать.

                                                            А так-то да, можно взять ICU за основу.
                                                              0
                                                              Так кто ж мешает Вам написать пропозал на основе ICU?
                                                                0
                                                                Уверяю, если я бы я решил писать предложения в комитет, то это было бы на первом месте. Однако гугл говорит что уже писали. Например вот предложение от 2013 года:
                                                                www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3572.html

                                                                Задача объёмная, скучная, но крайне важная, в отличие от концептов и т.п. Даже не представляю, сколько там человеко-часов надо, но точно одному не справиться.
                                                                  +1
                                                                  в отличие от концептов и т.п.
                                                                  Кому как.
                                                            +2
                                                            авторы стандарта делают не то что надо людям
                                                            комитет рассматривает те предложения, которые к нему поступают от любых заинтересованных сторон. На сколько я могу судить, не нашлось никого, кто бы проработал достаточно качественное и востребованное предложение по юникоду.
                                                    +1

                                                    О, к слову о constexpr vector. Что там с использованием памяти в рантайме, выделенной в компилтайме? Вандервуд говорил, что там есть какие-то мелкие проблемы, которые собирались устранить к C++20.


                                                    Охота уже в компилтайме строчку построить и в рантайме её использовать без костылей типа создания const char strRepr[] с рассчитываемым размером и рассчитываемым содержимым.

                                                      0
                                                      Эти проблемы пока не устранили. Так что память, выделенную через new в constexpr vector в рантайм пока просто так не поместить. Надо будет vector аккуратно возвращать как std::array или как-то подругому хитрить.
                                                        0

                                                        А в чём там проблема-то? Я по обсуждению с тем же Вандервудом так и не понял, что мешает выделенную в компилтайме через new память считать statically allocated storage, возможно, с какой-то там константностью.

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

                                                            А чем это отличается от попытки освобождения, э, обычной статической памяти?


                                                            Обзываете это UB и не паритесь. Вас же не смущает, что если вы сделаете delete [] указателю на статический массив, у вас будет UB?

                                                              –1
                                                              Так а чем сделать некоторое поведение UB лучше чем не поддерживать такое поведение вовсе? Хочется же не только шашечки, но и ехать.
                                                                0

                                                                Так у вас уже освобождение статической памяти — UB. Вы же не предлагаете поэтому выкинуть статически выделенную память?

                                                                  0
                                                                  Вот переехал у нас vector из компайлтайма в рантайм. Откуда ему знать, что память в _data статическая и удалять её не надо?
                                                                    +3

                                                                    Что значит «переехал»? Типа, лайфтайм одного и того же объекта начался в компилтайме и закончился в рантайме?

                                                                      0
                                                                      именно это я и имел в виду
                                                                        0

                                                                        А можно пример? Я что-то не уверен, что такое вообще возможно.

                                                                          0
                                                                          а почему не выделять эту память на стеке? То есть что бы компилятор вставлял объект в стек, будто он был создан в рантайме?
                                                                            0
                                                                            Не стек, а хип. А хип — это сразу какие-то сервисы от операционной системы, точно повторить которые компилятор не в состоянии…
                                                                              0
                                                                              почему хип? Если компилятор собрал объект и способен поместить его в статическую память, то почему не в стек? С хипом тоже не понял, почему компилятор не может поместить код для размещения в хипе в рантайме, также как он это делает в обычных случаях?
                                                                                +1
                                                                                Я чуток подумал, и понял, что был не совсем прав. Я напрочь забыл о существовании placement new (поскольку не пользовался никогда).
                                                                                Кажется, компилятору уже прямо сейчас ничего не мешает эмулировать этот placement new и класть полученный массив байтиков в .data. Проблема, как я понимаю, объяснить всем окружающим, что delete для этого объекта вызывать нельзя, он вместо освобождения памяти устроит чёрт-знает-что.

                                                                                Ну и статическая память (секция .data в частности) и стек — это разные вещи. Заранее инициализированное нечто (с фиксированным адресом) — это data.

                                                                                Почему компилятор не может сам разместить данные в хипе? Давайте попробую объяснить ещё раз.
                                                                                Он может сделать это следующим образом: в компил-тайм просчитать содержимое объекта (выполнить конструктор) и собрать стартап-код, который при старте программы:
                                                                                — вызывает менеджер памяти операционки
                                                                                — копирует в полученную область заранее посчитанный массив байтиков.
                                                                                Для сколь-нибудь сложных объектов (вектор — уже достаточно сложный) процедура нетривиальная, там и malloc'ов несколько, и содержимое объекта зависит от адресов, которые вернул malloc…

                                                                                Disclaimer. я неплохо представляю, как работает компилятор + стандартная библиотека на baremetal, но с «большими» операционками так глубоко не погружался (работает — и ладно). Возможно, где-то выше написана лажа.
                                                        +2

                                                        Горшочек, не вари!

                                                          +4
                                                          А что делать горшочку?
                                                            +2
                                                            Пеки? Жарь? Копти?
                                                              +4
                                                              Есть легкое ощущение натягивания совы на глобус от деятельности комитета.
                                                              У меня не хватает квалификации, чтобы аргументированно критиковать. Но с моей колокольни выглядит как добавление мало нужных фич в язык, просто чтобы были.
                                                                0
                                                                А какие фичи нужны вам?
                                                                  +2
                                                                  Да я как раз за то, чтобы не трогать язык какое-то время. :)
                                                                  Последнее чему радовался — введение override.
                                                                  Но, повторюсь, я средненький плюсовик, поэтому моё мнение не имеет значения.
                                                                    +2
                                                                    Модули модули модули
                                                                      +1
                                                                      Модули, stacktrace, reflection, убрать все _ из ключевых слов. Заставить (не знаю каким образом) компиляторы выдавать сообщения обошибках в одну строку а не на пять экранов и 100 килобайт на ошибку. Избавиться от .h файлов вообще. Нормальные строки, а не нуль-терминированные. Строковую интерполяцию через $"{x}" в format. Бинарную совместимость скомпилированых модулей между компиляторами. И т.д. Простые вещи, которые реально облегчают жизнь. Накой мне constexpr, если ошибка в нем дает сообщение в 5 килобайт? Я лучше вообще не буду ими пользоваться.
                                                                        +3
                                                                        Модули, stacktrace, reflection

                                                                        будут

                                                                        — Заставить компиляторы выдавать сообщения обошибках в одну строку а не на пять экранов и 100 килобайт на ошибку.
                                                                        — Избавиться от .h файлов вообще.
                                                                        — Строковую интерполяцию через $"{x}" в format.
                                                                        — Бинарную совместимость скомпилированых модулей между компиляторами

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

                                                                        — Нормальные строки, а не нуль-терминированные

                                                                        В чем проблема нуль-терминированности строк?
                                                                          0
                                                                          image

                                                                          М — Модули

                                                                          Вроде выглдядит свежо. Модули уже работают с системой сборки build2 и компилятором clang. Дерзайте!

                                                                          Только пишите инклуды перед объявлением модуля, а то будет вообще мясо в консоле, никогда не угадаете в чем ошибка
                                                                +1
                                                                Почему stacktrace отклонили? Есть ли шанс увидеть его в С++23?
                                                                  +2
                                                                  На него просто не хватило времени у LWG. К C++23 уж точно должен прорасти в стандарт.

                                                                  Благо в Кёльне stacktrace прошёл группу Core, так что самое страшное — позади. Теперь не надо думать, как описать stacktrace в терминах абстрактной машины, у которой в принципе нет стека.
                                                                    +1
                                                                    Теперь не надо думать, как описать stacktrace в терминах абстрактной машины, у которой в принципе нет стека.

                                                                    Вот это мне непонятно. Когда я компилирую С++ в FPGA или ASIC там действительно нет стека, все функции либо инлайнятся, либо генерируются в отдельные модули. Но ведь например и std::filesystem на такой машине тоже нет (хотя можно реализовать).

                                                                    Так почему стек не может быть опциональной фичей стандартной библиотеки, поддерживаемой на отдельных таргетах?
                                                                      +1
                                                                      Может. Но даже в этом случае его надо описать в терминах стандарта (абстрактной машины без стека)
                                                                  +6
                                                                  #include <type_traits>
                                                                  
                                                                  template<typename T>
                                                                  struct Optional {
                                                                      // ...
                                                                      ~Optional() requires(std::is_trivially_destructible_v<T>) = default;
                                                                      ~Optional() requires(!std::is_trivially_destructible_v<T>) {
                                                                          if (inited_) reinterpret_cast<T&>(data_).~T();
                                                                      }
                                                                  private:
                                                                      bool inited_{false};
                                                                      std::aligned_storage_t<sizeof(T), alignof(T)> data_;
                                                                  };
                                                                  

                                                                  И потом жалуются что у Rust слишком чужеродный синтаксис для людей из мира С++. Может оно и к лучшему?
                                                                    +6
                                                                    Мало кто пишет свой optional и суровые шаблоны, так что подобное редко увидешь в обычном коде. Но даже при этом код похож на вменяемый английский и его можно прочитать.

                                                                    В отл от яз прог прив выш: где `let y: &mut i32 = &x` или `let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();`
                                                                      +2
                                                                      В отл от яз прог прив выш: где let y: &mut i32 = &x или let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();

                                                                      Свежий шедевр подобного рода (отсюда):


                                                                      static UNIT: &'static &'static () = &&();
                                                                      
                                                                      fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
                                                                      
                                                                      fn bad<'a, T>(x: &'a T) -> &'static T {
                                                                          let f: fn(&'static &'a (), &'a T) -> &'static T = foo;
                                                                          f(UNIT, x)
                                                                      }
                                                                        +4

                                                                        Хаскелистами-факториальщиками запахло. Одобряю.

                                                                          0
                                                                          Если что – это бессмысленная отстебятина из ЛОРа. Первая строка – объявление статической переменной, являющейся ссылкой на ссылку на пустой кортеж. Остальное еще более бессмысленно, хоть и корректно синтаксически.
                                                                            +4

                                                                            Это не бессмысленная отсебятина, а MCVE для бага класса soundness hole

                                                                              +4
                                                                              Именно поэтому это точно не хороший пример кода на Rust в ветке с холиваром про синтаксис, согласитесь. :)
                                                                                +1

                                                                                Хороший пример. Если уж плюсофобы выпадают в осадок от возможности сделать несколько деструкторов (чем будут пользоваться доли процента от действующих программистов на C++), то почему бы не показать пример Rust-о-кода, с которым имеют дело доли процентов действующих программистов на Rust?

                                                                                  +1

                                                                                  с учетом того, что пример для C++ из стандартной библиотеки (куда здоровые люди обычно не смотрят--шутка), то это сопоставимые примеры

                                                                            –2

                                                                            Вы специально усложнили код. Благодаря выводу типов код можно упростить до let y = &x или let mut parts = MaybeUninit::uninit();. Зачем вы набрасываете?

                                                                              +3
                                                                              Затем что я копировал код из реального проекта, и ничего не набрасывал.

                                                                              Я понятия не имею что написано в этой строчке, но сами авторы Rust считают что надо писать так. Ну и да, всё это разумеется завёрнуто в unsafe :)
                                                                                +1
                                                                                То что это завернуто в unsafe намекает что эту дичь написали чтобы остальные разработчики пользовались удобными интерфейсами и в целом спали спокойно.

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

                                                                                Мало кто, знаете ли, пишет на Rust стандартную библиотеку языка. :)
                                                                                  +2
                                                                                  Автор изменил коммент, так что мой не имеет смысла уже… del
                                                                                    +2
                                                                                    Я не вижу в этом проблемы. Уникальность Rust в его дуальности: по одну сторону safe Rust, гарантирующий разработчику safety, а по другую сторону unsafe Rust в котором как раз разработчик должен обеспечить выполнение всех инвариантов. За счет объединения этих двух миров под одной крышей как раз и достигаются те самые бесплатные абстракции, которые не протекают если вы подставите им неожиданный тип в шаблон или передадите не ту ссылку в соседний поток.

                                                                                    На счет конкретного этого примера:

                                                                                    let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit();

                                                                                    В действительности этот код полностью аналогичен:

                                                                                    let mut parts = MaybeUninit::uninit();

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

                                                                                    Да, этот код написан в угоду производительности (еще раз, это стандартная библиотека), и чтобы код был еще и корректным используются специфические конструкции типа MaybeUninit. Вообще если изучить стандартную библиотеку Rust она в своей реализации целиком состоит из unsafe блоков и другой черной магии. Но это точно не показатель что код на Rust именно такой. Как раз наоборот: всю отстебятину скрыли за простыми интерфейсами, чтобы обычные разработчики могли писать сложный и безопасный код пользуясь простыми интерфейсами.
                                                                                      +2
                                                                                      Ну и «безотносительно ЯП»: бесплатные абстракции и бескомпромиссные безопасность с производительностью – это фишка Rust.

                                                                                      Кому-то такой подход может не подходить как раз из-за того что «такой код мейнтейнить новым разработчикам в разы сложнее отчего позже ими пишутся новые костыли и велосипеды, так как разбираться почему именно так долго не будут». Ничего страшного, для таких случаев есть масса других хороших языков, вроде Python или даже Java.

                                                                                      Ставка делается на то «такого кода» в вашем проекте будет от силы несколько процентов, даже если вы пишете что-то относительно низкоуровневое. Весь остальной код будет как раз таки проще мейнейнить, потому что новым разработчикам не нужно держать в голове всех ньюансов использования этого кода – ньюансы заложены в интерфейсы, за которыми спрятан unsafe.
                                                                                        0
                                                                                        Я не читал что вы написали по трём причинам:
                                                                                        * вы не вдумываетесь в то что вам пищут в ответ
                                                                                        * синтаксис Rust страшен до жути, отрицать это бессмысленно
                                                                                        * мне интересны технические споры, но (увы) ни один из спорщиков про Rust не в состоянии рассказать какие возможности по оптимизации кода даёт/забирает та или иная особенность Rust.

                                                                                        Вместо этого споры идут на дошкольном уровне.

                                                                                        Удивите меня, расскажите не просто о своём любимом ЯП. Расскажите о том, как используя опыт и подходы из вашего любимого ЯП сделать C++ лучше.
                                                                                          +6
                                                                                          Если вы тыкаете меня в то что решили не снисходить читать мой комментарий, почему я должен распинаться и пытаться удивить вас?

                                                                                          Хотите технической дисскусии – задайте технические вопросы и не опускайтесь до уровня «синтаксис Rust страшен до жути, отрицать это бессмысленно».
                                                                                            0
                                                                                            Почему Rust не предаёт знания об алиасинге middle endу, из-за чего генерируется менее эффективный код?

                                                                                            Почему у Rust такое соглашение по вызовам? Чем обоснован существующий возврат значений из функций, с большим количеством записи на стек?

                                                                                            Почему не стали использовать SSO строки в стандартной библиотеке Rust?
                                                                                              0

                                                                                              3: А зачем? Это не является вопросом уровня дизайна языка. Хочется микрооптимизаций в конкретном месте — просто добавь библиотеку: https://crates.io/crates/inlinable_string


                                                                                              1: Потому что это еще не успели сделать? Неужели раст настолько медленней плюсов (нет), что силы разработчиков стоит кидать на такую задачу?

                                                                                                +2
                                                                                                Научный мир отказывался долгое время переходить с Fortran на C++ как раз из-за алаисинга (в Fortran вроже как этой проблемы нет в принципе).

                                                                                                Вот мне и интересно: почему важная оптимизация, преимущество перед многими другими языками программирования ещё не сделана? Есть технические проблемы?
                                                                                                  +5

                                                                                                  Да, есть технические проблемы.


                                                                                                  Алиасинг был сделан, но полезли баги вроде этой:
                                                                                                  https://github.com/rust-lang/rust/issues/54462. Оказалось, что ллвм генерирует некорректный код, поэтому noalias выключили до лучших времен: https://github.com/rust-lang/rust/pull/54639. Текущее состояние: написали пример на С с restrict, который генерирует некорректный код и в кланге, и в гцц: https://github.com/rust-lang/rust/issues/54878#issuecomment-429578187


                                                                                                  Созданы соответствующие баг репорты:
                                                                                                  https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87609
                                                                                                  https://bugs.llvm.org/show_bug.cgi?id=39282

                                                                                                    0

                                                                                                    Как говорилось, потому что раст использует &mut намного чаще, чем плюсовики restrict, поэтому когда раст начал везде расставлить noalias посыпались баги ллвм, и эту аннотацию отключили.


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

                                                                                                  +1
                                                                                                  > Почему Rust не предаёт знания об алиасинге middle endу, из-за чего генерируется менее эффективный код?

                                                                                                  Можно чуть более конкретный пример? В Rust реализуются оптимизации связанные с алиасингом или c гарантией его отсутствия.

                                                                                                  > Почему у Rust такое соглашение по вызовам? Чем обоснован существующий возврат значений из функций, с большим количеством записи на стек?

                                                                                                  Опять же, что имеется ввиду? Соглашение по вызовам у Rust наследуется от С++, и определятеся скорее LLVM. Или речь о возврате Result<T, E>?

                                                                                                  > Почему не стали использовать SSO строки в стандартной библиотеке Rust?

                                                                                                  Потому что это нарушило бы некоторые гарантии при работе со строками (отсутствие неявных копирований и перемещений при вызове некоторых методов). String – это по определению обертка над Vec, который в свою очередь является выделенной памятью на куче. Если вам нужны массивы или строки произвольной длины на стеке, есть соответсвующие крейты: smallvec и inlinable_string.
                                                                                                    0
                                                                                                    String – это по определению обертка над Vec

                                                                                                    Ну во-первых не по определению, а во-вторых, наивная реализация строки является наименее производительной из возможных.
                                                                                                      0
                                                                                                      Во-первых, как раз по определению:
                                                                                                      A String is made up of three components: a pointer to some bytes, a length, and a capacity. The pointer points to an internal buffer String uses to store its data. The length is the number of bytes currently stored in the buffer, and the capacity is the size of the buffer in bytes. As such, the length will always be less than or equal to the capacity. This buffer is always stored on the heap.

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

                                                                                                      Я бы назвал это не наивной реализацией, а базовой, потому что на ее основе реализуется в том числе вариант с SSO. Вполне логично что в стандартной библиотеке языка реализуются именно базовые структуры данных, а не «более эфективные», потому что лучшая эфективность как правило достигается ценой ограничений вылезающих из какой-нибудь другой стороны.

                                                                                                      При этом, я сам в нескольких проектах использовал smallvec и inlinable_string, так что ничего против такого подхода не имею.
                                                                                                        –1
                                                                                                        Это документация конкретной имплементации, а не определение.

                                                                                                        Приведите примеры приложений, когда SSO менее эффективен чем наивная реализация. Во всех случаях что я видел — прирост производительности всего приложения весьма ощутим, т.к. динамические аллокации крайне дорогие.

                                                                                                        Какие оптимизации SSO отменяет?
                                                                                                          –1

                                                                                                          SSO делает более дорогими операции перемещения. Тут как раз в комментариях к недавнему посту на это жаловались.

                                                                                                            0
                                                                                                            Дайте пожалуйста ссылку на пост
                                                                                                              +1
                                                                                                                +2
                                                                                                                Там в коментариях люди забыли добавить нетривиальный деструктор (даже без SSO надо освобождать за собой память, деструктор будет нетривиальгый). С ним разница между SSO и его отсутствием нет godbolt.org/z/jWrvsv на libc++

                                                                                                                А вот libstdc++ чудит godbolt.org/z/z0VabY. Попробую на досуге поправить имплементацию std::basic_string.

                                                                                                                Есть примеры где SSO вредит?
                                                                                                              +4
                                                                                                              Вы про вот этот комментарий? Во-первых, два лишних mov и один xor это копейки, несравнимые с аллокаций/деаллокацией/копированием памяти в куче. Во-вторых, khim ошибся и в своем коде забыл занулить буфер из которого делается move (с настоящей строкой так делать нельзя). Вот так правильно, и… мне кажется, или я вижу одинаковый код?
                                                                                                                0
                                                                                                                Если бы вы прочитали мой комментарий до конца, то увидели бы, что я про то, почему там зануление есть — как раз отлично знаю.

                                                                                                                А ваш код, извините, добавляет лишнее действие: разумеется условные «малые» строки (которые в принципе никогда ничего в куче не аллоцируют) при std::move зануления не требуют… Как, кстати, и libc++'ые… Кстати хорошая идея — можно попробовать его ещё чуток ускорить… Нужно только первый байт же обнулять…
                                                                                                                  0

                                                                                                                  Я ту дискуссию не читал, но почему? В строке же могут быть нулевые символы.

                                                                                                                    0
                                                                                                                    Потому что так устроен C++. После того, как вы «забрали» строку в другую «объедки» должны быть валидной строкой. И, в частности, у строки должна быть возможность вызвать деструктор!

                                                                                                                    То есть по-минимуму нужно в строке из который «забрали» содержимое дёрнуть флажок, чтобы она не попыталась память освобождать, когда деструктор вызвали. А вот почему, при этом, libc++ обнуляет строку полностью — не знаю, надо будет посмотреть…
                                                                                                                      0

                                                                                                                      Я, наверное, упустил контекст, но мы же обсуждаем случай SSO и строки такой длины, которая под SSO подходит? Если да, то зачем там что-то забирать и флажки какие-то выставлять?

                                                                                                                        0
                                                                                                                        Вообще-то SSO — это «Small String Optimization» здесь. Там могут быть как короткие строки (прям внутри объекта), так и длинные (в куче).

                                                                                                                        Мы не знаем — короткая там строка или длинная. Мы просто «забираем» содержимое «как есть».

                                                                                                                        Если строка таки реально была короткая — ты мы «в шоколаде» и у нас после этого уже и так всё хорошо.

                                                                                                                        А если длинная? Тогда нужно сделать так, чтобы «старая» строка стала валидной, но на тот буфер, который она использовала раньше больше не ссылалась.

                                                                                                                        Иначе у нас окажутся две строки — и каждая будет считать, что она владеет буфером. В какой-то момент отработают два деструктора и… в общем хорошо не будет.

                                                                                                                        Для того, чтобы этого не случилось libc++ обнуляет всю строку… хотя это излишне: достаточно было бы обнулять первый байт (признак «малой строки»).

                                                                                                                        Написать им, об этом, что ли?

                                                                                                                        P.S. Альтернатива — это различать в нашем конструкторе «короткие» и «длинные» строки и обрабатывать их по разному. Но это плохая идея: даже сейчас у нас «лишних» действий — три лишних инструкции обнуляющие «старую» строку. А если сделать так, чтобы обнулялся только первый байт — вообще одна инструкция останется. А проверка плюс переход — это точно будет дороже…
                                                                                                                          0
                                                                                                                          Альтернатива — это различать в нашем конструкторе «короткие» и «длинные» строки и обрабатывать их по разному. Но это плохая идея: даже сейчас у нас «лишних» действий — три лишних инструкции обнуляющие «старую» строку. А если сделать так, чтобы обнулялся только первый байт — вообще одна инструкция останется. А проверка плюс переход — это точно будет дороже…

                                                                                                                          Мне это неочевидно (ну там, бранч предиктор, все дела), но ваши предпосылки я понял, и в таких предположениях с вами согласен.

                                                                                                                          0
                                                                                                                          Если да, то зачем там что-то забирать и флажки какие-то выставлять?

                                                                                                                          Если строка длинная, так делать нельзя. А проверка на короткость строки дороже, чем тупо занулить исходную.
                                                                                                                      0
                                                                                                                      разумеется условные «малые» строки (которые в принципе никогда ничего в куче не аллоцируют) при std::move зануления не требуют…

                                                                                                                      диллема в том, что в с++ неудаляющий мув, из-за чего мув и деструктор могут друг друга не видеть. А так да, в определенных случаях компилятор может зануление с деструктором оптимизировать.
                                                                                                                  –2
                                                                                                                  Подозреваю что в тех примерах которые вы видели прирост производительности достигается за счет того что при создании пустых строк не выделяется память на хранение \0. В Rust это и так не происходит, поскольку строки не заканчиваются на \0, а на пустой вектор память не выделяется.
                                                                                                                    +1
                                                                                                                    Пустые строки ничего динамически не аллоцировали даже без SSO, за исключением одной имплементации, которая уже больше 20 лет так не делает.

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

                                                                                                                    Смиритесь, SSO работает. По каким причинам его не внедрили по умолчанию в Rust?
                                                                                                                      +2
                                                                                                                      Vec will never perform a «small optimization» where elements are actually stored on the stack for two reasons:

                                                                                                                      It would make it more difficult for unsafe code to correctly manipulate a Vec. The contents of a Vec wouldn't have a stable address if it were only moved, and it would be more difficult to determine if a Vec had actually allocated memory.

                                                                                                                      It would penalize the general case, incurring an additional branch on every access.

                                                                                                                      doc.rust-lang.org/std/vec/struct.Vec.html#guarantees
                                                                                                                      0
                                                                                                                      Подозреваю что в тех примерах которые вы видели прирост производительности достигается за счет того что при создании пустых строк не выделяется память на хранение \0.

                                                                                                                      выделять память под пустую строку банально незачем. Чтобы c_str() указывал на null-terminated буфер достаточно либо возвращать указатель на саму строку (как это сделано во всех текущих реализациях), либо возвращать указатель на статически выделенный нулевой байт (как это делал gcc до 5-й версии).
                                                                                                                    0
                                                                                                                    Во-первых, как раз по определению:

                                                                                                                    Определение реализации строки в расте != определение «строки» в более общем, межъязыковом смысле. В общем случае гарантии вектора как «heap-allocated contiguous array» строке не нужны. А вот что строке нужно, так это производительность в типовых сценариях.

                                                                                                                    Во-вторых, совсем не факт что предложенная реализация будет однозначно эфективнее во всех случаях

                                                                                                                    судя по бенчмаркам (некоторые привел даже автор inlinable_string), это скорее факт чем нет.

                                                                                                                    При этом, я сам в нескольких проектах использовал smallvec и inlinable_string, так что ничего против такого подхода не имею.

                                                                                                                    привет оверхеду на конвертации String <-> inlinable_string, особенно в проектах опирающихся на кучу библиотек с разным API.
                                                                                                                      –1
                                                                                                                      Определение реализации строки в расте != определение «строки» в более общем, межъязыковом смысле.
                                                                                                                      Ух ты, готовы дать строгое и полное определение «строки» в общем, межъязыковом смысле? :)

                                                                                                                      Я согласен что в общем случае гарантии реализации Rust не нужны, но когда дело доходит до реализации вам прийдется дать какое-то определение того, что вы называете строкой, и это определение сразу же наложит ограничения на то, чем она не является. Например вы скажете, что строка – это последовательность байт, которая является валидным utf-8. Сразу же найдется кто-то, кто скажет что это неэффективно, потому что нельзя быстро переместиться к i-ому символу в строке. Если бы вы использовали utf-32, нашелся бы кто-то другой, кто сказал бы что строки занимают в 4 раза больше памяти. Сделаете оба варианта – будут жаловаться на то что нет единообразия и тратится время на конвертацию, сделаете один тип с поддержкой нескольких вариантов – будут жаловаться на накладные расходы каждый раз в тех случаях, где используется только одна кодировка.

                                                                                                                      судя по бенчмаркам (некоторые привел даже автор inlinable_string), это скорее факт чем нет.
                                                                                                                      То что показывают бенчмарки можно было узнать и без них – что маленькие строки из литералов создаются быстрее. То как это отражается на работе всех остальных методов и как это влияет на работу в условиях приближенных к реальности это не показывает. Автор сам пишет что «These are very micro benchmarks and your (hashtag) Real World workload may differ greatly».

                                                                                                                      Я в своих проектах не заметил статистически значимого изменения производительности в случае применения SSO, хотя там как раз было много работы с маленькими строками. Конечно, это только один случай.

                                                                                                                      привет оверхеду на конвертации String <-> inlinable_string, особенно в проектах опирающихся на кучу библиотек с разным API.
                                                                                                                      В большинстве случаев библиотеки зависят от строковых слайсов (&str, &mut str), а не от строк (String). В этом плане не важно как именно вы их создали или храните – как String или inlinable_string. При этом у inlinable_string (как и у любой реализации SSO) будут чуть большие накладные расходы на получение строкового слайса – это тоже необходимо учитывать. Если библиотека должна писать что-то, то как правило используется типаж Write, как раз потому что ответственность на выборе места, куда записывать данные лежит на пользователе библиотеки. Так что тут inlinable_string тоже не сыграет роли.
                                                                                                                        +1
                                                                                                                        Автор сам пишет что «These are very micro benchmarks and your (hashtag) Real World workload may differ greatly».

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

                                                                                                                        Я в своих проектах не заметил

                                                                                                                        Бенчмаркали? И что в вашем понимании «статистически значимое изменение»?

                                                                                                                        В большинстве случаев библиотеки зависят от строковых слайсов (&str, &mut str), а не от строк (String)

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

                                                                                                                        При этом у inlinable_string (как и у любой реализации SSO) будут чуть большие накладные расходы на получение строкового слайса – это тоже необходимо учитывать

                                                                                                                        Вы до сих пор не понимаете что оверхед SSO (пара инструкций) на 3 десятеричных порядка меньше оверхеда от честной копии?
                                                                                                                          0

                                                                                                                          В расте отсутствует неявный оператор копирования строк, роэтому ситуация с честными копиями видна по расставленным .clone(), которые можно оптимизировать в &str. &str — это типа string_view, только с корректным времени жизни.

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

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

                                                                                                                                +1
                                                                                                                                из влияющих на производительность разность подхода только одна — там, где система типов раста не гарантирует корректность, программист редко напишет unsafe ради микрооптимизации. Перед плюсовиком такая дилемма не стоит в принципе.
                                                                                                                            +1
                                                                                                                            авторов не один, бенчмарк не один, некоторые из них взяты из реальных сервисов
                                                                                                                            Я в курсе, я тоже чуть-чуть приложился к этой библиотеке, когда она только появилась.
                                                                                                                            И когда приложение, работающее с текстом, выигрывает 10% или более от одной лишь замены реализации строки, наверно, ваша теория не верна?
                                                                                                                            Какая моя теория? Хорошо если выигрывает, пользуйтесь библиотекой на здоровье. Мы же обсуждали должно ли это быть поведением по-умолчанию для всех сервисов.
                                                                                                                            Бенчмаркали? И что в вашем понимании «статистически значимое изменение»?
                                                                                                                            Статистически значемое изменение – это если разница в результатах бенчмарков хотя бы больше стандартного отклонения последовательности измерений. В случае моей задачи это было не так, хотя вроде бы часто использовались строки маленького размера.
                                                                                                                            логично, что можно передавать слайс (что выливается в лишние аллокацию/копирование/деаллокацию если эту строку надо где-то сохранить), если копия наивно реализованной строки будет в точности такой же дорогой.
                                                                                                                            Зачем вообще что-то копировать если можно хранить строковый слайс?
                                                                                                                            Вы до сих пор не понимаете что оверхед SSO (пара инструкций) на 3 десятеричных порядка меньше оверхеда от честной копии?
                                                                                                                            Точно 3 десятичных порядка? Вы уверены? Даже на самом экзотическом микробенчмарке вы получите до 100x. В тоже время, если вы много работаете с большыми строками, «пара инструкций» оверхеда у вас появляется на буквально каждое обращение к данным в строке.

                                                                                                                            Я не собираюсь утверждать что реализация String на Rust эфективнее и лучше чем SSO, я предлагаю вам не быть так однозначно уверенным в обратном.
                                                                                                                              0
                                                                                                                              Зачем вообще что-то копировать если можно хранить строковый слайс?

                                                                                                                              это если лайфтайм позволяет

                                                                                                                              Даже на самом экзотическом микробенчмарке вы получите до 100x

                                                                                                                              «самый экзотический микробенчмарк» я запущу в несколько потоков, увеличивая стоимость атомиков в аллокаторе )

                                                                                                                              В тоже время, если у вас большие строки, «пара инструкций» оверхеда у вас появлется на каждое обращение к строке.

                                                                                                                              Если у меня большая строка, дополнительные 3-4 инструкции на взятие пары итераторов попросту потеряются. Чего не скажешь о короткой строке и её аллокации.
                                                                                                                    +2
                                                                                                                    > Соглашение по вызовам у Rust наследуется от С++

                                                                                                                    Что-то непохоже. На простейших функциях Rust делает раза в три больше обращений к стеку godbolt.org/z/vzUEpJ

                                                                                                                    Почему выбран такой подход? Чем он обоснован?
                                                                                                                      0
                                                                                                                      Пример с алиасингом: godbolt.org/z/WsrusD

                                                                                                                      В ассемблерном коде от Rust идёт перечитывание данных по адресам (dword ptr[регистр]), в то время как код C++ с __restrict этого не делает (что намного эффективнее). Если уберёте __restrict, то увидите что код C++ и Rust совпадут один в один.
                                                                                                                    +2
                                                                                                            0
                                                                                                            Именно это и делает изначальный пример — заворачивает дичь с микрооптимизацией optional чтобы остальные разработчики пользовались удобными интерфейсами и в целом спали спокойно.

                                                                                                            Так что примеры эквивалентны, не понимаю почему вырвиглазная нечитаемая дичь Rust лучше хотя бы читаемой вырвиглазной дичи C++.
                                                                                                              +4
                                                                                                              А я своим изначальным комментарием как раз и хотел донести что С++ разработчики жалуются на Rust только потому что своя дичь роднее. Я когда-то давно думал что немного знаю C++, но глядя на это:

                                                                                                              ~Optional() requires(!std::is_trivially_destructible_v<T>) {
                                                                                                                 if (inited_) reinterpret_cast<T&>(data_).~T();
                                                                                                              }

                                                                                                              понимаю что вижу только нечитаемую вырвиглазную дичь, как и вы в Расте.
                                                                                                                +5
                                                                                                                Мне вот интересно когда вы немного знали C++? В 1990м?

                                                                                                                Тут нет ни одной синтаксической формы, которой не было в C+98 (есть requires, но он, синтаксически, вполне подобен throws, который в C++98 уже был).
                                                                                                                  +1

                                                                                                                  Но тут все эти синтаксические формы собрались вместе.

                                                                                                                    –3
                                                                                                                    Я отвечу вам честно: я специально полез в гугл узнать зачем используется "~" в С++, потому что я забыл. Тильда для вызова деструктора, серьезно? Это выглядит понятным только для тех, кто пользуется этим каждый день.

                                                                                                                    Тут выше писали что Rust нечитабелен потому что вместо понятных слов используются специальные символы. Так вот С++ ни чуть не лучше в этом плане, его заслуга лишь в том что этот язык уже знает большое количество программистов.
                                                                                                                      +3
                                                                                                                      Тильда для вызова деструктора, серьезно?
                                                                                                                      Серьёзнее некуда: деструктор именно так и описывался начиная с Turbo C++ 1.01. Может в каких-то ранних версиях «C с классами» и было по-другому, не знаю, но во всех известных мне компиляторах деструктор описывается именно так.

                                                                                                                      Это выглядит понятным только для тех, кто пользуется этим каждый день.
                                                                                                                      Эээ… Для вас «выглядит странным», что функцию можно вызвать по её имени? Вы точно на C++ хотя бы «Hello, world!» написали?

                                                                                                                      Так вот С++ ни чуть не лучше в этом плане, его заслуга лишь в том что этот язык уже знает большое количество программистов.
                                                                                                                      Ну с этим, как раз, спорить бесполезно. Как я уже сказал — мне куда больше по душе Ада… Хотя там тоже есть всякие апострофы. Похоже от идеи использовать «закорючки» разработчики ЯП никогда не откажутся.

                                                                                                                      Но в данном-то случае, как бы, речь идёт о самом центральном элементе языка, центральное некуда: C++, как известно, изначально вообще назывался «C с классами», так что классы — это центральная вещь в C++, прямо из названия понятно… а одной из важнейших «фишек» классов в C++ как раз и являются конструктор и деструктор…

                                                                                                                      Так-то да, действительно дичь… но это ж не что-то, что в C++20 появилось — это то, что в C++ было всегда
                                                                                                                        +4
                                                                                                                        Может тильда для обозначения деструктров в С++ и была всегда, но если представить на секунду что С++ это не центр вселенной программирования, и что есть куча альтернативных языков программирования, которые выражают это иначе (можно допустить что даже лучше), то такое обозначение начнет выглядеть слегка бессмысленным. Просто представьте что вы не знаете С++ и вам нужно догадаться что делает «foo.~T()». Именно на это я и хотел намекнуть, когда говорил что забыл значение этой конструкции. (Мне стыдно, но это правда!)

                                                                                                                        Был бы там какой-нибудь foo.drop() или delete foo, такой проблемы не возникло бы. Но люди из мира С++ часто склонны считать что если что-то было всегда или давно (в С++), значит это и есть наиболее правильное положение вещей. Я даже боюсь представить что будет если сказать что отсутствие хоть какого-то ключевого слова для объявления функции или метода явно не прибавляет читабельности языку. :)
                                                                                                                          0
                                                                                                                          Просто представьте что вы не знаете С++ и вам нужно догадаться что делает «foo.~T()».
                                                                                                                          В этом случае, да, можно себе все мозги сломать. Но вы-то сказали, что его знаете немного — а тут уж про деструктор можно бы и вспомнить. Тем более что с этой самой тильды весь пример начался: ~Optional()… в первой строке. Там, почему-то, тильда вас не смутила.

                                                                                                                          Просто, ну не знаю… прямой вызов деструктора в C++ действительно — черезвычайно редок… Но он же, в сущности, синтаксически такой же, как вызов любой другой функции!

                                                                                                                          Ну то же самое, что с выражением Obj->*FPtr(...); — писать такое приходится редко, но я видел очень мало людей, которые бы, встретив эту конструкцию первый раз в жизни, её бы не опознали… То же самое и здесь…
                                                                                                                            0
                                                                                                                            Знал и конечно же реализовывал деструкторы, последний раз лет 8 назад. Такой паузы оказалось достаточно чтобы вообще не понять что передо мной вызов и объявление деструктора. Я решил что это унарный оператор и на этом мой парсер сломался.
                                                                                                              0

                                                                                                              Вы же скопировали кусок стандартной библиотеки. Мало кто пишет свою стандартную библиотеку...

                                                                                                                0
                                                                                                                Вы верно подметили, optional (с которого началась данная дискуссия) — это часть стандартной библиотеки.
                                                                                                          +1
                                                                                                          ну, по-моему, это вполне читаемо и понятно. Да, требует знаний выше среднего, но «середняки» не пишут свои шаблонные либы.
                                                                                                            +1

                                                                                                            Как это, неужели не я один считаю синтаксис Раста лапшеобразным?

                                                                                                              0
                                                                                                              Скорее фаршик
                                                                                                                +2
                                                                                                                Можно пожалуйста пример того что вы имете ввиду?
                                                                                                                  0
                                                                                                                  Да там все один сплошной пример. Открываешь официальные растбуки, открываешь любой проект на гитхабе, просто статью на хабре случайно увидел, и каждый раз глаза сочатся кровью. Они даже от современного С++ так не сочатся.

                                                                                                                  Естественно я не возражаю, если вы считаете иначе.
                                                                                                                    +4
                                                                                                                    Вы не думали, что дело только в привычке? Человеку, который много лет пишет, например, на Python, С++ будет казаться крайне вырвиглазным. Код шаблонов с использованием std::enable_if вместо указания типа и тому подобное — это же вообще кошмар. Но тем кто пишет на C++ эта магия шаблонов — нормально.

                                                                                                                    Как пример, изначально мне крайне не понравился даже синтаксис объявления функций и аргументов в Rust (я знаю что тут возвращаемый тип можно было не указывать, просто для демонстрации синтаксиса указал):
                                                                                                                    fn a_plus_b(a: i32, b: i32) -> i32
                                                                                                                    {
                                                                                                                        a + b
                                                                                                                    }
                                                                                                                    Только чем больше времени проходит, тем больше я понимаю, что разработчики Rust не зря выбрали именно такой синтаксис объявления типа результата функции и типов аргументов и переменных, отказавшись от привычного синтаксиса C++. Тем более, что в сам C++ ввели похожую форму задания типа результата через "->", и появилось это именно из-за того, что выбранный первоначально синтаксис не везде подходит (при указании возвращаемого типа через decltype() в шаблонах, и в лямбдах). То есть в C++ есть как минимум два разных синтаксиса для объявления одного и того же, и вот это вполне себе обычный C++:
                                                                                                                    auto a_plus_b(uint32_t a, uint32_t b) -> uint32_t
                                                                                                                    {
                                                                                                                        return a + b;
                                                                                                                    }

                                                                                                                    Впрочем, я до сих пор ещё не пишу на Rust. Так, присматриваюсь. Споткнусь на очередную вещь, которая мне не нравится, и потом жду, когда до меня наконец дойдёт, почему было сделано именно так, и тогда уже смотрю дальше =)
                                                                                                                      0
                                                                                                                      Вы не думали, что дело только в привычке?


                                                                                                                      «В том числе в привычке» — да. Но не «только».

                                                                                                                      Код шаблонов с использованием std::enable_if вместо указания типа и тому подобное — это же вообще кошмар


                                                                                                                      Да, и именно поэтому меня воротит от шаблонов. Впрочем я не настоящий сварщик, так что мне норм.

                                                                                                                      Только чем больше времени проходит, тем больше я понимаю, что разработчики Rust не зря выбрали именно такой синтаксис объявления типа результата функции и типов аргументов и переменных, отказавшись от привычного синтаксиса C++


                                                                                                                      Конечно не зря — надо же как-то выделиться… Обычно в этом месте вспоминаются какие-то хитрые случаи, когда именно такой синтаксис спас человека с редкой болезнью (но это не точно).

                                                                                                                      Тем более, что в сам C++ ввели похожую форму задания типа результата через "->", и появилось это именно из-за того, что


                                                                                                                      Из-за того, что кто-то пытается натянуть С++ на глобус, со всеми этими шаблонами и лямбдами. Строго имхо конечно.
                                                                                                                        +2
                                                                                                                        Из-за того, что кто-то пытается натянуть С++ на глобус, со всеми этими шаблонами и лямбдами.
                                                                                                                        Если вам не хочется ничего изучать, то есть же C89, в чём вопрос?

                                                                                                                        А то у вас получается: зачем в самолёте лонжероны и элероны — понятия не имею, кому колёс и рамы-то, вдруг, не хватило.

                                                                                                                        Вообще основная проблема с Rust'ом — это даже не то, что он многословен (тут всегда выбор между лаконичностью и точностью описания), а вт эт вт обрз на рвн мст. Зачем превращать программу в ребус? Вроде XXI век на дворе, телевизоры с разрешением 40x25 символов уже никто для редактирования не пользует…
                                                                                                                          0
                                                                                                                          Если вам не хочется ничего изучать, то есть же C89, в чём вопрос?


                                                                                                                          Обождите, не надо утрировать. Во-первых, даже если ограничить себя миром Си, то С89 — очевидно не лучший выбор. Во-вторых я не предлагаю ограничиться Сями, плюсы прекрасны же. Речь была о том, что некоторые вещи вводятся в С++ имхо из принципа «ну давайте еще и вот это», даже если весь остальной язык при этом трещит.

                                                                                                                          Вообще основная проблема с Rust'ом — это даже не то, что он многословен (тут всегда выбор между лаконичностью и точностью описания), а вт эт вт обрз на рвн мст. Зачем превращать программу в ребус?


                                                                                                                          Ээээ, вы точно сами написали этот комментарий? Просто я как раз с этим очень согласен, да, все эти ребусы ни к чему, можно написать чуть больше слов… Но ведь вы же сами в соседней ветке меня убеждали, что если все то же самое написать многословнее, то это будет боль и беда… А теперь пишете обратное.
                                                                                                                            +1
                                                                                                                            Речь была о том, что некоторые вещи вводятся в С++ имхо из принципа «ну давайте еще и вот это», даже если весь остальной язык при этом трещит.
                                                                                                                            Пример можно? Потому что я знаю про вещи, которые мало на что влияют (скажем возможность писать вложенные namespaces через ::), которые, действительно, могут вводиться «шоб було»… но при этом и негативного эффекта без них — мизер.

                                                                                                                            А вот разные фичи типа способа записи типа после функции — они вполне конкретные проблемы решают.

                                                                                                                            Но ведь вы же сами в соседней ветке меня убеждали, что если все то же самое написать многословнее, то это будет боль и беда…
                                                                                                                            Где? Я как раз к синтаксису rust, скорее отрицательно отношусь. Но вот идеи, которые в нём заложены — дело другое.

                                                                                                                            А синтаксис… мне может быть сколько угодно нравиться синтаксис Ады и не нравиться C++, но, увы, C++ — банально «мощнее», многие выразимые в нём концепции в Ада нереализуемы в принципе.
                                                                                                                              0
                                                                                                                              которые, действительно, могут вводиться «шоб було»… но при этом и негативного эффекта без них — мизер


                                                                                                                              Я не говорю, что они кому-то мешают, просто… ну слишком много их.

                                                                                                                              Где? Я как раз к синтаксису rust, скорее отрицательно отношусь.


                                                                                                                              Ну помните было обсуждение, где я неосмотрительно назвал Си близким к ассемблеру языком? Вот там в итоге все дошло и до Раста.

                                                                                                                              А синтаксис… мне может быть сколько угодно нравиться синтаксис Ады и не нравиться C++, но, увы, C++ — банально «мощнее», многие выразимые в нём концепции в Ада нереализуемы в принципе.


                                                                                                                              Ну а как же надежность ПО?! Кто будет отвечать за вот это вот все!
                                                                                                                              Ваш саркастический тролль
                                                                                                                                +1
                                                                                                                                Ну а как же надежность ПО?!
                                                                                                                                А никак.

                                                                                                                                Кто будет отвечать за вот это вот все!
                                                                                                                                А никто. Такова жизнь. Надёжное ПО не продаётся. Смиритесь.

                                                                                                                                То есть рассказывать о том, как вы заботитесь о надёжности и безопасности — это можно, тут есть выгода. А вот реально делать что-либо безопасное и надёжное — невыгодно, об этом ведь речь шла.

                                                                                                                                Ну помните было обсуждение, где я неосмотрительно назвал Си близким к ассемблеру языком? Вот там в итоге все дошло и до Раста.
                                                                                                                                Там Rust выступал как надёжный язык. Но ни разу, нигде я не говорил о том, что он красив и удобен.

                                                                                                                                Это разные вещи: я вполне признаю что Rust — это большой шаг вперёд в смысле надёжности (даже с учётом того, что да, у него в borrow checker'е есть ошибки), однако его синтаксис… синтаксис ужастен.

                                                                                                                                Как я уже сказал в смысле синтаксиса мне больше Ада нравится… но она ни как C++, ни, тем более, как Rust — не умеет. Увы.
                                                                                                                                  0
                                                                                                                                  Там Rust выступал как надёжный язык. Но ни разу, нигде я не говорил о том, что он красив и удобен.


                                                                                                                                  Ну, наверное я вас как-то не так понял.

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

                                                                                                                                  Как я уже сказал в смысле синтаксиса мне больше Ада нравится… но она ни как C++, ни, тем более, как Rust — не умеет. Увы.


                                                                                                                                  Это все на самом деле все к тому же вопросу — чем проверять «когда же уже треснет этот язык от нововведений», может проще не набивать его сверх меры? Есть те, кто считают Аду, Оберон и прочих вполне достаточными в своем текущем виде. А кому-то нужны всякие приколюхи… Ну так идите в другой язык ради этого, выбор ведь огромный, и специфический инструмент обычно лучше швейцарского ножика.

                                                                                                                                  Впрочем это все неважно, если уж люди задались целью сделать «язык для всего».
                                                                                                                                    0
                                                                                                                                    Есть те, кто считают Аду, Оберон и прочих вполне достаточными в своем текущем виде.
                                                                                                                                    Вот только где они? Я таких не знаю. Людей, которые считают их красивыми — знаю (сам такой), а вот «достаточными»… нет, не видел. Давно уже не видел.

                                                                                                                                    А кому-то нужны всякие приколюхи… Ну так идите в другой язык ради этого, выбор ведь огромный, и специфический инструмент обычно лучше швейцарского ножика.
                                                                                                                                    Далеко не всегда, увы. А «маленькие», «красивые» языки — так и вообще редко когда оказываются достаточными. Недаром сейчас даже в embedded всё больше C++ и всё меньше C…
                                                                                                                                      0
                                                                                                                                      Недаром сейчас даже в embedded всё больше C++ и всё меньше C


                                                                                                                                      По этому поводу еще раз спрошу, а то вы в прошлый раз не ответили — что вы думаете о том, чтобы в 2019 году писать на С++ 03 (то бишь 98), ну или, если более широко, вообще о концепции ограниченного использования С++ в эмбеде? Это просто вопрос, без намеков и подвоха.
                                                                                                                                        +1

                                                                                                                                        Я не khim, но не понимаю, зачем ограничивать себя не рантайм-фишками (отключение rtti или экзепшонов понять можно), а уровнем стандартов языка.

                                                                                                                                          0
                                                                                                                                          Представьте себе, что это неважно — зачем и почему. Просто есть, положим, такая идея — ограничить себя НЕиспользованием каких-то новых фич. возможно это ограничение придумано даже не нами, но существует.
                                                                                                                                            +1

                                                                                                                                            Звучит как религия.

                                                                                                                                          0
                                                                                                                                          В принципе согласен с 0xd34df00d.

                                                                                                                                          Я могу понять отказ от C и C++, как от небезопасных.

                                                                                                                                          Но отказ от C++ в пользу C — понять не могу: уровень безопасности у них одинаков («никакой» в обоих случаях, к сожалению), а выразительная сила C++ гораздо выше. VLA (чуть не единственная фича C, отсутствующая в C++) в embedded вроде не особо нужны…

                                                                                                                                          Используя C вы получаете всё недостатки ограниченной выразительности Ada/Rust и не получаете гибкости C++ — зачем себя так мучить?
                                                                                                                                            0
                                                                                                                                            Ну Торвальдс аргументирует (в моей интерпретации) тем, что эта выразительность не стоит той запутанности кода, которая из неё происходит при реальных применениях. С++ способствует скрытию противоречий и снижает очевидность кода более чем С, если я правильно понимаю суть аргумента Торвальдса.
                                                                                                                                              +1

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

                                                                                                                                                0
                                                                                                                                                Я не уверен, что аргумент Торвальдса напрямую угрожает Хаскелю, т.к. Хаскель — полная противоположность С++ в этом плане. С++ позволяет делать что угодно и поверх этого чего-угодно натягивать абстракции и сверлить в них любые дырки. Хаскель же запрещает больше чем С. Вопрос, правда, в том, удобно ли на Хаскеле написать всё что надо так, что бы компилятор мог это оптимизировать до уровня производительности С-кода.
                                                                                                                                                Что такое «типокукаретиковой»? :)
                                                                                                                                                  +2

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


                                                                                                                                                  Вопрос, правда, в том, удобно ли на Хаскеле написать всё что надо так, что бы компилятор мог это оптимизировать до уровня производительности С-кода.

                                                                                                                                                  В пределе умных компиляторов — да. Ну или можно eDSL делать, в конце концов.


                                                                                                                                                  Что такое «типокукаретиковой»? :)

                                                                                                                                                  Это «теория типов» плюс немного самоиронии, чтобы не звучать пафосно.

                                                                                                                                                    0
                                                                                                                                                    уровень абстракций в хаскеле, ну, ещё повыше
                                                                                                                                                    а дырявят их часто?
                                                                                                                                                      0

                                                                                                                                                      Хороший вопрос. Я не очень понимаю, что такое дырявая абстракция, если абстракция идёт откуда-то из алгебры.


                                                                                                                                                      Ну вот Hask не категория, например. Или система типов не формирует консистентную логику. Считать ли это дырками — хз.


                                                                                                                                                      Вот seq + undefined точно дырка.

                                                                                                                                                0
                                                                                                                                                Вы правильно понимаете аргументы Торвальдса, но забываете, что они писались больше 10 лет назад.

                                                                                                                                                В C++11/14/17/20 появилось много вещей, которые могут быть полезны как раз для ситуаций, когда нужен контроль над низкоуровенвыми аспектами. Но с его мнением по поводу STL и Boost я, пожалуй, соглашусь: уже даже банальный std::string может оказаться слишком тяжёлым для embedded. Но вот, например, сопрограммы — могут позволить сделать некоторые вещи куда как более надёжным и эффективным способом, чем в C++. Хотя за ними нужно следить, так как они, увы, могут аллоцировать память — а в embedded это не рекомендуется.
                                                                                                                                                  0
                                                                                                                                                  В C++11/14/17/20 появилось много вещей, которые могут быть полезны как раз для ситуаций, когда нужен контроль над низкоуровенвыми аспектами


                                                                                                                                                  Что-то я не понял, как это препятствует «скрытию противоречий в коде».
                                                                                                                                                    0
                                                                                                                                                    Что-то я не понял, как это препятствует «скрытию противоречий в коде».
                                                                                                                                                    Это добавляет вещей, которые можно с пользой использовать в низкоуровневом коде.

                                                                                                                                                    В чём-то Линус прав: в C++ слишком много соблазнов и слишком много вещей, которые стоят больше, чем в embedded мире можно себе позволить.

                                                                                                                                                    Но как раз вещи, появившиеся в C++11/14/17 — зачастую позволяют сделать код меньше и не требуют тяжёлых поддерживающих библиотек. Это существенно изменяет баланс по отношению к C++98.
                                                                                                                                                    0
                                                                                                                                                    В C++11/14/17/20 появилось много вещей, которые могут быть полезны как раз для ситуаций, когда нужен контроль над низкоуровенвыми аспектами.
                                                                                                                                                    Но старые практики, которые ведут к непонятному или обманчивому когду, всё равно не получается запретить. К сожалению.
                                                                                                                                                    вещи, появившиеся в C++11/14/17 — зачастую позволяют сделать код меньше
                                                                                                                                                    это добавляет преимуществ (которые и так есть), но не устраняет недостатков [по сравнению с С].
                                                                                                                                                    за ними нужно следить, так как они, увы, могут аллоцировать память
                                                                                                                                                    а это вообще реально на практике? Предполагается какой-то ключ типа "--couroutine-never-allocate"?
                                                                                                                                                      0
                                                                                                                                                      Но старые практики, которые ведут к непонятному или обманчивому когду, всё равно не получается запретить. К сожалению.
                                                                                                                                                      Ну тут ничего не поделать, увы.

                                                                                                                                                      а это вообще реально на практике? Предполагается какой-то ключ типа "--couroutine-never-allocate"?
                                                                                                                                                      Насколько я знаю нет. Но там используется указанный вам operator new, можно его не описать, но нигде не определять — тогда ликер это сможет отловить… но это будет зависеть от уровня оптимизации…
                                                                                                                                                    0
                                                                                                                                                    С++ способствует скрытию противоречий в коде более чем С


                                                                                                                                                    Да, причем не только Торвальдс об этом говорит.
                                                                                                                                                    0
                                                                                                                                                    Используя C вы получаете всё недостатки ограниченной выразительности Ada/Rust и не получаете гибкости C++ — зачем себя так мучить?


                                                                                                                                                    Вообще говоря все процитированное очень спорно, но это и неважно. Я не предлагаю отказываться от С++ в пользу С, вопрос был только о том, чтобы ограничить себя каким-то устаревшим стандартом.
                                                                                                                                                      +1
                                                                                                                                                      Я не предлагаю отказываться от С++ в пользу С, вопрос был только о том, чтобы ограничить себя каким-то устаревшим стандартом.
                                                                                                                                                      А вот это как раз — очень плохая идея. Вещи, добавляемые в стандарт не из пальца высасываются.

                                                                                                                                                      Скажем возьмите то же метапрограммирование. Чтобы не сойти с ума в C++98 вам придётся использовать MPL, в C++11 — Hana, а в C++17… всё необходимое — есть в стандартной библиотеке и многие полезные вещи делаются гораздо проще, чем в C++98… даже с использованием MPL или Hana
                                                                                                                                                        –2
                                                                                                                                                        А вот это как раз — очень плохая идея. Вещи, добавляемые в стандарт не из пальца высасываются.


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

                                                                                                                                                        Собственно и упоминание C++03 не просто так — это база для MISRA C++2008. Это пока не выступает ограничителем в нашем частном случае, но может.
                                                                                                                                                          +1
                                                                                                                                                          Вы же поняли, что я не просто так спрашиваю, а из серии show your practices.
                                                                                                                                                          А они просты: включаем -std=c++17 в сборке, но запрещаем все фичи в Style Guide. Потом добавляем потихоньку те, которые полезнее всего (самыми полезными оказались лямбды в нашем случае — просто-нипросто гораздо удобнее делать callback'и).

                                                                                                                                                          Пока фичу нельзя продемонстрировать в конкретном месте в конкретном случае — никому знать как она работает и не нужно, а когда потребуется — так есть несколько CLей, показывающих «как надо».
                                                                                                                                                            +1
                                                                                                                                                            А они просты: включаем -std=c++17 в сборке, но запрещаем все фичи в Style Guide. Потом добавляем потихоньку те, которые полезнее всего


                                                                                                                                                            Отлично, привожу пример — понадобились только std::array (и то я хз, какова будет его ценность при отключенных прерываниях, разве что совсем уж глупые ошибки в компилтайме ловить), неймспейсы и классы (просто классы, любим инкапсуляцию и синтаксический сахар в виде конструкторов). Ииии… и что, это «modern C++»?
                                                                                                                                                              +3
                                                                                                                                                              А вам надо, чтобы был «modern C++»… или чтобы работало?

                                                                                                                                                              Не гоняйтесь за фичами ради фич — но смотрите на то, где вы можете упростить и/или ускорить код с использованием оных… и вы удивитесь как быстро даже самые новые вещи, вдруг, окажутся востребованными.

                                                                                                                                                              Посмотрите на возможности уменьшения copy-paste с помощью шаблонов, посмотрите что вы можете вынести из рантаймов в компайл-тайм через constexpr и так далее.

                                                                                                                                                              Главное — не пытайтесь использовать фичу потому, что она «модная». То же метапрограммирование — отличная вещь, но… Если вместо пяти функций на пять строк вы напишите одну на сто… оно вам надо? А вот если одну функцию на двести строк вместо сотни функций по три строки — другое дело же!
                                                                                                                                                                0
                                                                                                                                                                Да ну нет, я-то естественно не собираюсь гнаться за новыми фичами, это для вас должно быть уже немного очевидно. Вопрос был о том, приемлемо ли не гнаться, и где проходит тот водораздел между можно и необходимо. Простейший пример — как понять, когда std::array вместо С-массива уже нужен, а когда еще нет? Если ответ на это для вас окажется простым, то вот посложнее — как понять, что вам реально нужен std::vector, а не что угодно другое вместо него? Понятно, что в обоих случаях мы говорим о ситуации отсутствия внешних ограничений, выбирать можно что угодно, мне просто интересно, что вы об этом думаете.

                                                                                                                                                                Я это спрашиваю потому, что фраза «и вы удивитесь как быстро даже самые новые вещи, вдруг, окажутся востребованными» кажется мне небесспорной. Классический пример — был какой-то локальный велосипед для решения какой-то задачи, потом внезапно стало можно убрать/изменить велосипед за счет решения, примененного в новом стандарте. Но… зачем? Старый велосипед отлажен и впилен во все мыслимые библиотеки. Проблема перехода на новые фичи ничуть не проще, чем проблема перехода на новые архитектуры.
                                                                                                                                                                  0
                                                                                                                                                                  Я, если честно, вообще не вижу проблемы. Если вы нового кода не пишите, а только меняете какие-то констранты где-то — то сам C++ вообще и новые фичи в частности, не нужны. А если вы пишите код и/или делаете рефакторинг — ну вот тогда и нужно вспомнить Мейрса и подумать — а нельзя ли тут написать проще, используя возможности C++.

                                                                                                                                                                  Выбор же структур данных — это вообще не наука, а искусство, если бы на него можно было в двух абзацах ответить, то не получали бы программисты вдвое-втрое больше, чем токари и сварщики…

                                                                                                                                                                  P.S. Начните с мелких фич — причём самых новых. Скажем с constexpr и static_assert: вы можете использовать constexpr-переменные и if constexpr чтобы гарантировать, что какие-то вещи вычислятся при сборке прошивки, а не будут повторно вычисляться 100500 раз. А заодно — часть вещей из прошивки просто уйдут. Полезно? Да. Сложно? Ну… отчасти: когда попробуете это сделать, то обнаружите «много интересного» в том коде, про который вы, вроде бы, всё понимали. Причём «интересного» в стиле «кто придумал сделать так, что вот это вот выражение, которое можно, вроде бы, посчитать статически, мы вычисляем 100500 раз в секунду и зря греем воздух»…
                                                                                                                                                                    –2
                                                                                                                                                                    А если вы пишите код и/или делаете рефакторинг — ну вот тогда и нужно вспомнить Мейрса и подумать — а нельзя ли тут написать проще, используя возможности C++


                                                                                                                                                                    Естественно вопрос именно об этой ситуации, когда планируется вообще новый проект (небольшой) и обсуждается спектр решений: С99 (как было), С++03 (если вдруг придется переносить в продуктовый контент), либо взять и забабахать С++14 например.

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


                                                                                                                                                                    Немного странная фраза, ибо теория резания например развита совершенно недостаточно для того, чтобы исключить понятие «хороший, опытный токарь», то есть как раз токарное дело — вполне себе искусство. А вот со структурами данных как раз таки обязана быть внятная система аргументов, наподобие упомянутой следующим комментатором.

                                                                                                                                                                    ы можете использовать constexpr-переменные и if constexpr чтобы гарантировать, что какие-то вещи вычислятся при сборке прошивки, а не будут повторно вычисляться 100500 раз


                                                                                                                                                                    А оно мне надо? Ну, серьезно, не стоит так уж рассуждать об эмбеде, будто там все те же 128 байт ОЗУ и 1к ПЗУ, и это повсюду. Ничего, я потерплю лишние вычисления… Впрочем разумеется вы правы, это вещь полезная, но как пример акцептации — так себе.

                                                                                                                                                                    static_assert


                                                                                                                                                                    На правах троллинга: есть же _Static_assert!