company_banner

Что приняли в C++17, фотография Бьярне Страуструпа и опрос для C++20


    В начале марта в американском городе Кона завершилась встреча международной рабочей группы WG21 по стандартизации C++ в которой участвовали сотрудники Яндекса.
    C++17 "приняли"!
    Если быть совсем точным, решили, что пора передавать документ-черновик С++17 в вышестоящий орган ISO, который выпустит его в качестве стандарта, либо отправит обратно для исправления форматирования и некоторых других формальностей.

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

    Основное время было посвящено полировке черновика C++17, но несколько небольших и интересных нововведений все же успели проскочить в C++17.


    20 лет ждали...


    std::ofstream(L"Теперь можно открывать файлы с юникодными именами.txt") << u8"Ура!";
    


    std::optional и сравнения


    Операторы сравнения для класса std::optional до последнего дня были описаны как:
    template <class T>
    bool operator < (const optional<T>&, const T&);
    // ...
    

    Что вызывало ошибки компиляции в ряде случаев:

    optional<const int> x = 42;
    int y = 666;
    x == y; // не скомпилируется
    ...
    
    optional<string> s = "Hello";
    s == "Hello"; // не скомпилируется
    


    В Коне эта проблема была исправлена, операторы сравнения приобрели следующий вид:
    template <class T, class U>
    bool operator < (const optional<T>&, const U&);
    // ...
    

    Так что теперь все вышеприведённые примеры будут компилироваться, а сравнение 's == «Hello»' будет работать без создания временного объекта строки.

    Deduction guides


    Было добавлено множество явных deduction guides, так что теперь следующий код будет собираться:

    // Ура! Можно не писать шаблонные параметры.
    std::tuple      a = {42, "Hello", 3.14};
    std::array      b = {1, 2, 3, 4, 5, 6, 7, 8};
    std::pair       c = {42, "Hello"};
    std::function   d = [](int i) { std::cout << i; };
    std::set        e = {1, 2, 3, 4, 5, 6, 7, 8};
    
    // P.S.: В примерах выше знак '=' тоже можно не писать :)
    


    История успеха std::array
    В первоначальной бумаге по интеграции explicit deduction guides в стандартную библиотеку не присутствовал класс std::array.

    Но так как этот класс любимый у одного из представителей России в WG21 C++, то мы закатали рукава, вооружились последними компиляторами, написали и оттестировали explicit deduction guides для std::array. После чего результат трудов выслали автору предложения, пообщались с ним в кулуарах и… вуаля!


    std::byte


    Кого-нибудь смущало, что когда нам нужен массив байт для хранения каких-то бинарных данных у мы заводили «массив беззнаковых букв»? C С++17 у нас будет тип данных std::byte и теперь вместо
    unsigned char raw_buffer[buffer_size];
    можно писать
    std::byte raw_buffer[buffer_size];
    .

    Мелочи, делающие код компактнее и портабельнее


    Множество небольших улучшений было внесено повсеместно в стандарт. Так например:
    • std::filesystem::path был подкручен для того, чтобы он мог корректно работать на платформах, отличных от Windows и POSIX (например, на zOS).
    • std::filesystem::directory_entry научился кешировать информацию от ОС и обходиться одним системным вызовом там, где раньше требовалось 2.
    • std::hash для большинства случаев теперь помечен как noexcept, что сделает размер ваших бинарников меньше (при условии, что вы пользуетесь unordered_* контейнерами).
    • Текст описывающий std::atomic_* функции был сильно переработан, теперь код
      long example(atomic<long> * a) { return atomic_fetch_add(a, 42); }
      гарантированно работает на всех имплементациях.
    • Все переменные-теги и шаблонные переменные были помечены как inline, что устраняет проблемы с потенциальным нарушением ODR. Другими словами, объём и производительность вашего код будут менее зависимы от линкера, работа линкера упростится.


    Обсуждения и идеи


    Как всегда, несколько подгрупп внутри комитета С++ работали одновременно. Некоторые подгруппы успели разобраться с задачами связанными с C++17, и приступили к продумыванию идей для C++20. Ниже расскажу о некоторых самых интересных обсуждениях.

    Numbers TS


    Если вы занимаетесь точными науками, разрабатываете сверхнадёжные приложения, участвуете в олимпиадах по программированию, ведете финансовые рассчёты или работаете с огромными числами, то у меня есть для вас хорошие новости. Сформировались планы по выпуску Numbers TS — набора различных классов для разнообразнейшей работы с числами. Вот некоторые кандидаты:
    • wide float — числа с плавающей точкой, где количество машинных слов под хранение числа задаётся на этапе компиляции;
    • wide integers (на основе предложения с stdcpp.ru) — целые числа, где количество машинных слов под хранение числа задаётся на этапе компиляции;
    • unbounded floats — числа с плавающей точкой, способные хранить число любой размерности и динамически аллоцирующие память по мере необходимости;
    • unbounded integers — целые числа, способные хранить число любой размерности и динамически аллоцирующие память по мере необходимости;
    • rational — дробные числа;
    • safe numbers — обертки над числами, гарантирующие отсутствие UB на этапе компиляции, либо проверяющие переполнения и UB на рантайме;
    • decimal;
    • small float.

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

    operator<=>()


    Обсудили operator<=>(). Решено продолжать проработку этого оператора, есть все шансы что к C++20 можно будет писать:
    struct foo { /* очень много различных полей */ };
    
    auto operator<=>(const foo&, const foo&) = default; // Сгенерирует все компараторы для сравнения foo c foo
    auto operator<=>(const foo&, const char*) = default; // Сгенерирует все компараторы для сравнения foo c const char* и все компараторы для сравнения const char* с foo
    


    Остальное


    А еще обсуждали модули, корутины/сопрограммы/«Гор-рутины», контракты, constexpr и constexpr контейнеры, constexpr аллокацию «в куче», плагины и динамическую загрузку библиотек, крутые оптимизации для стандартных контейнеров и много другое. Рассказать всё в одном посте не получится, поэтому мы в РГ 21 планируем небольшую встречу, на которой расскажем о будущем С++ и о С++17 поподробнее. Так же на встрече будет выступать Гор Нишанов — автор корутин для WG21 C++.

    Итоги и опрос


    C++17 на подходе, ура!

    Если у вас есть идеи для C++20, вы нашли проблемы в C++17/C++14/C++11, или просто хотите подстегнуть разработку той или иной фичи C++, то заходите на сайт рабочей группы stdcpp.ru. Добро пожаловать!

    Внимание! Некоторым подгруппам международного комитета С++ нужно получить информацию о том, что разработчикам интересно и чем разработчики пользуются, чтобы лучше расставить свои приоритеты.
    Итак, вот мини опрос:
    • 51%Можно научить контейнеры доставать информацию о действительном размере выделенного куска памяти из аллокатора, что сделает контейнеры стандартной библиотеки более производительными и менее затратными по памяти (например в тесте вот тут получили 15% прирост производительности при вставке в вектор). Вам эта разработка интересна?195
    • 41%Используете ли вы в компании, или в своих личных проектах, плагины/динамическую-загрузку-библиотек? Опишите в комментариях, какими функциями и классами вы для этого пользуетесь?156
    • 14%Используете ли вы в компании, или в своих личных проектах, классы способные хранить числа произвольной длинны (unbounded integers) с нестандартными аллокаторами?54
    • 6%Применяете ли вы один нестандартный аллокатор для всего бинарника целиком (вместо использования специфичного аллокатор именно для unbounded integers)?24
    • 2%Переопределяете ли вы в аллокаторе для unbounded integers тип pointer на имитирующий поведение указателя класс?9
    • 68%Вам нужны модули, не экспоритрующие макросы и максимально быстрые при компиляции?259
    • 38%Вам нужны модули, экспоритрующие макросы и позволяющие с большей лёгкостью переносить старый код на модули?147

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

    Яндекс 527,70
    Как мы делаем Яндекс
    Поделиться публикацией
    Похожие публикации
    Комментарии 314
    • +3
      По поводу плагинов в виде .dll/.so: приходилось использовать и очень активно. Вначале использовались свои обертки вокруг «родного» API OS, затем перешли на работу посредством ACE.
      • +1
        А можете сообщить подробности? Коротким сравнительным примером простого кода. Чтобы воочию увидеть суть различий и возможные преимущества/недостатки.
        • 0
          Подробности забылись где-то в районе 2004-2005 годов, когда мы заменяли свои древние, самописные велосипеды (которые из которых росли еще со времен OS/2) на ACE. Основная причина была в том, что глупо было тянуть собственные разработки и заниматься их багфиксингом и модернизацией, когда все готовое уже было в ACE. Включая и средства для работы с DLL.
          • 0
            Скажите, пожалуйста, хотя бы, что такое ACE? ;-)
            • 0
              Adaptive Communication Environment — очень крутая для своего времени кросс-платформенная библиотека, абстрагирующая C++ разработчика от низкоуровневых деталей конкретных ОС.

              Сейчас выглядит ну очень олдскульно и зачастую может быть заменена Boost-ом или POCO. Тем не менее, если знаний C++ недостаточно для разбирательства с потрохами Boost-а на какой-нибудь богом забытой платформе, то ACE вполне может быть достойным выбором и сегодня. ИМХО. конечно.
      • +1
        Когда я смотрел на код библиотеки std, мне всегда казалось, что его писали инопланетяне. У меня есть один принцип: я никогда не использую в своих проектах код, который выглядит ужасно.
        • +1
          А что не так с кодом std? Можно пример?
          • +19

            Он очень красивый (нет)


                explicit vector(size_type _Count)
                    : _Mybase()
                    {   // construct from _Count * value_type()
                    if (_Buy(_Count))
                        {   // nonzero, fill it
                        _Alty _Alval(this->_Getal());
                        _TRY_BEGIN
                        _Uninitialized_default_fill_n(this->_Myfirst, _Count, _Alval);
                        this->_Mylast += _Count;
                        _CATCH_ALL
                        _Tidy();
                        _RERAISE;
                        _CATCH_END
                        }
                    }
            
            • +4
              Внимание, вопрос: как вы думаете, а почему код написан именно так? Какие на то причины?
              • +10
                чтобы в отладчике сразу понять, что вы залезли не туда? =)
                • 0
                  Просветите нас?
                  • +12
                    Ниже практически всё подметили:
                    * нижние подчеркивания перед всем что только можно — чтобы защитить себя от пользователей, пишущих макросы в нижнем регистре
                    * вместо throw/try/catch — макросы, так как многие пользователи используют стандартную библиотеку с выключенными исключениями
                    * большие и длинные тела if — оптимизация под конкретный компилятор (разработчик знает где у него hot path и знает какую ветку компилятор делает hot path). Некоторые стандартные библиотеки имеют в телах goto по той же причине — знают косяки своего компилятора и написали goto чтобы сгенерировался более оптимальный код
                    * Множество макросов так же делают библиотеку юзабельной для разных версий стандарта. Так libstdc++ работает на флагах -std=(gnu++98,gnu++03,gnu++11,gnu++14,gnu++1z,c++98,c++03,c++11,c++14,c++1z), без макросов напободие _GLIBCXX_NOEXCEPT просто не обойтись.
                    * Есть макросы, которые позволяют работать без RTTI (так любят делать embedded разработчики)
                    * Другие странности форматирования (например после открывающей фигурной скобки отступ в -4 пробела) связаны с очень древними кодовыми базами… когда мониторы были узкие и вся С++ строчка иначе на экран не помещалась
                    * Куча плясок с бубном вокруг аллокаторов (поэтому много всякого метапрограммирования и специфичные typedef для указателей, вместо T*). Все для того, чтобы пользовательские аллокаторы с using pointer = fancy-pointers работали
                    * Куча плясок с бубном вокруг точек кастомизации — поэтому часть методов помечены как ::std::, другие методы вызываются без указания namespace
                    * Много плясок с бубном вокруг исключений — практически всё что пользователь передал в качестве шаблонного параметра может кинуть исключение в любой момент. После такого исключения надо оставаться в валидном состоянии (да, даже если функция хеширования кинула исключения — надо подчистить ресурсы и остаться в валидном состоянии).
                    * Некоторые имплементации поддерживают дебажные версии стандартной библиотеки, из-за чего макросов становится еще больше, а странность кода возрастает в угоду производительности в дебажном режиме
                    *… (я что-то наверняка забыл)
                  • +2
                    Причина одна, — недостаточно качественный язык, в котором нельзя выразить этот код нормально, без макросов.

                    Понятно, что скорее всего для совместимости с разными стандартами языка и разными моделями исключений, но код ужасен.
                    • +1
                      Это не макросы (в коде выше)
                  • +3
                    В середине 90-х слышал байку, что реализацию STL для MS VC++ писал большой любитель Lisp-а и делал он это на каком-то вполне себе читабельном DSL-е. Из которого уже генерировалось вот этот вот все непотребство с нечитабельными именами. Причем нечитабельные имена были выбраны специально. Вроде как даже несколько причин было для этого: начиная от того, что первые реализации STL должны были работать даже на компиляторах без поддержки namespaces, и заканчивая тем, чтобы не возникало конфликтов имен у пользователей, если кто-то отнаследуется от std::vector и захочет добавить парочку своих атрибутов в класс-наследник.

                    Понятно, что байка. Но когда заглядываешь в исходники некоторых реализаций STL в нее начинаешь верить :)

                    Тем не менее, об STL-е нужно судить не по коду самого STL (там вполне ожидаемо буде хардкор, непонятный половине действующих C++ников), а по коду, который использует STL.
                    • 0
                      Вроде как наследоваться некомильфо из-за отсутствия виртуальных деструкторов, не?
                      • 0
                        Все не так просто. В двух словах: такое наследование не будет проблемой, если нет удаления наследника через указатель на базу. Что, вообще-то говоря, нужно бывает далеко не всегда. Плюс, в современном C++ тот же shared_ptr временами может закрывать и эту проблему.
                    • 0

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

                      • 0

                        Будем восстанавливать справедливость :)

                      • +1
                        libc++ приятнее
                        • +2
                          Честно говоря, не вижу ничего криминального. Для стандартной библиотеки вполне допустимо жертвовать читабельностью ради совместимости и производительности.
                          Тем более что ничего непонятного в этом коде нет (и в коде ниже тоже). Любой, кто понимает что такое вектор, с лёкостью прочитает этот код.
                          • +1
                            Майерс «Эффективное использование STL»
                            http://cpp.com.ru/meyers/ch7.html

                            В глаза бросается упоминание шаблона std::_Tree. В Стандарте ничего не сказано о шаблоне с именем Tree, но мы помним, что имена, начинающиеся с символа подчеркивания и прописной буквы, зарезервированы для авторов реализаций. Перед нами один из внутренних шаблонов, используемых в реализации некой составляющей STL.

                            Оказывается, практически во всех реализациях STL стандартные ассоциативные контейнеры (set, multiset, map и multimap) строятся на основе базовых шаблонов. По аналогии с тем, как при использовании string в диагностике упоминается тип basic_string, при работе со стандартными ассоциативными контейнерами часто выдаются сообщения с упоминанием базовых шаблонов. В данном примере этот шаблон называется _Tree, но в других известных мне реализациях встречались имена tree и _rb_tree, причем в последнем имени отражен факт использования красно-черных (Red-Black) деревьев, самой распространенной разновидности сбалансированных деревьев, встречающейся в реализациях STL.


                            • 0
                              Интересно, а если бы пользователь библиотеки (он же программист) мог бы сам выбирать реализацию шаблонов и алгоритмов, то как это всё выглядело бы?
                              • 0

                                Глядя на текущий код реализации, вы действительно хотите это знать?

                                • 0

                                  Наверное в виде шаблонных параметров.
                                  Но зачем это может понадобиться?

                            • +14

                              Он классный (нет)


                                  iterator _Insert_n(const_iterator _Where,
                                      size_type _Count, const value_type& _Val)
                                      {   // insert _Count * _Val at _Where
                               #if _ITERATOR_DEBUG_LEVEL == 2
                                      if (_VICONT(_Where) != this
                                          || _VIPTR(_Where) < this->_Myfirst
                                          || this->_Mylast < _VIPTR(_Where))
                                          _DEBUG_ERROR("vector insert iterator outside range");
                               #endif /* _ITERATOR_DEBUG_LEVEL == 2 */
                              
                                      size_type _Off = _VIPTR(_Where) - this->_Myfirst;
                                      if (_Count == 0)
                                          ;
                                      else if (_Unused_capacity() < _Count)
                                          {   // not enough room, reallocate
                                          if (max_size() - size() < _Count)
                                              _Xlen();    // result too long
                              
                                          size_type _Capacity = _Grow_to(size() + _Count);
                                          pointer _Newvec = this->_Getal().allocate(_Capacity);
                                          size_type _Whereoff = _VIPTR(_Where) - this->_Myfirst;
                                          int _Ncopied = 0;
                              
                                          _TRY_BEGIN
                                          _Ufill(_Newvec + _Whereoff, _Count,
                                              _STD addressof(_Val));  // add new stuff
                                          ++_Ncopied;
                                          _Umove(this->_Myfirst, _VIPTR(_Where),
                                              _Newvec);   // copy prefix
                                          ++_Ncopied;
                                          _Umove(_VIPTR(_Where), this->_Mylast,
                                              _Newvec + (_Whereoff + _Count));    // copy suffix
                                          _CATCH_ALL
                                          if (1 < _Ncopied)
                                              _Destroy(_Newvec, _Newvec + _Whereoff);
                                          if (0 < _Ncopied)
                                              _Destroy(_Newvec + _Whereoff, _Newvec + _Whereoff + _Count);
                                          this->_Getal().deallocate(_Newvec, _Capacity);
                                          _RERAISE;
                                          _CATCH_END
                              
                                          _Count += size();
                                          if (this->_Myfirst != pointer())
                                              {   // destroy and deallocate old array
                                              _Destroy(this->_Myfirst, this->_Mylast);
                                              this->_Getal().deallocate(this->_Myfirst,
                                                  this->_Myend - this->_Myfirst);
                                              }
                              
                                          this->_Orphan_all();
                                          this->_Myend = _Newvec + _Capacity;
                                          this->_Mylast = _Newvec + _Count;
                                          this->_Myfirst = _Newvec;
                                          }
                                      else if ((size_type)(this->_Mylast - _VIPTR(_Where))
                                          < _Count)
                                          {   // new stuff spills off end
                                          value_type _Tmp = _Val; // in case _Val is in sequence
                              
                                          _Umove(_VIPTR(_Where), this->_Mylast,
                                              _VIPTR(_Where) + _Count);   // copy suffix
                              
                                          _TRY_BEGIN
                                          _Ufill(this->_Mylast,
                                              _Count - (this->_Mylast - _VIPTR(_Where)),
                                              _STD addressof(_Tmp));  // insert new stuff off end
                                          _CATCH_ALL
                                          _Destroy(_VIPTR(_Where) + _Count,
                                              this->_Mylast + _Count);
                                          _RERAISE;
                                          _CATCH_END
                              
                                          this->_Mylast += _Count;
                                          _Orphan_range(_VIPTR(_Where), this->_Mylast);
                                          _STD fill(_VIPTR(_Where), this->_Mylast - _Count,
                                              _Tmp);  // insert up to old end
                                          }
                                      else
                                          {   // new stuff can all be assigned
                                          value_type _Tmp = _Val; // in case _Val is in sequence
                              
                                          pointer _Oldend = this->_Mylast;
                                          this->_Mylast = _Umove(_Oldend - _Count, _Oldend,
                                              this->_Mylast); // copy suffix
                              
                                          _Orphan_range(_VIPTR(_Where), this->_Mylast);
                                          _Copy_backward(_VIPTR(_Where), _Oldend - _Count,
                                              _Oldend);   // copy hole
                                          _STD fill(_VIPTR(_Where),
                                              _VIPTR(_Where) + _Count, _Tmp); // insert into hole
                                          }
                                      return (begin() + _Off);
                                      }
                              • +2

                                Ну кроме микрософтовского есть еще и другие, например, libc++. Но в целом причина тут в том, что метапрограммирование на шаблонах родилось весьма стихийно, по просту говоря, создавали их для более простых вещей, а уже в процессе поняли, что их можно использовать куда хитрее, а дальше понеслась.
                                Хорошая новость в том, что не обязательно в своем коде писать так-же.

                                • 0
                                  Что будет, если подвергнуть этот код пресловутому рефакторингу?
                                • +5

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

                                  • +1
                                    его не по прихоти безумцев так пишут. Плюс, вам этот код не поддерживать, не менять и даже не читать, а только использовать.
                                    • +12

                                      Я считаю, что именно по прихоти безумцев. Человек в своем уме не мог принять такой кодестайл и именование входных параметров и переменных. Читать его не приходится ровно до первого мисюза какой-нибудь обычной функции. Дальше вываливается пару килобайт ошибок в консоль, которые прочитать невозможно из-за дикого именования, потом я иду смотреть код… И мне приходится его читать!

                                      • +6
                                        Дальше вываливается пару килобайт ошибок в консоль

                                        Во-первых, метод поиска ошибок через чтение кода стандартной библиотеки наименее эффективен независимо от её кода. Ошибка всё-таки у вас, а не там. Во-вторых, пользуйтесь нормальной IDE. В-третьих, грядут концепты, а с ними диагностические сообщения проще. И, последнее, вы приводите код из майкрософтовской реализации и критикуете язык с++ что этот код плохо написан?
                                        • +4
                                          пользуйтесь нормальной IDE

                                          Какую-такую "нормальную IDE" рекомендует использовать коммитет стандартизации с++? Может они начнут нам рассказывать, какими инструментами нам пользоваться?

                                          • +2
                                            И, последнее, вы приводите код из майкрософтовской реализации и критикуете язык с++ что этот код плохо написан?

                                            т.е. вот этот код лучше?

                                            • +1
                                              Какую-такую «нормальную IDE» рекомендует использовать коммитет стандартизации с++?

                                              При чем тут комитет? Нормальную IDE вам советую я. Причем даже не какую-то определенную
                                              т.е. вот этот код лучше?

                                              да
                                              • +2
                                                А ведь libc++, который вам советовали, действительно симпатичнее даже «вот этого» кода.
                                                </irony>
                                            • +3

                                              Именование переменных такое специально, чтобы их имена не могли пересекаться с вашими. Это даже в стандарте прописано. Сами авторы реализаций постоянно над этим иронизируют, и даже термин придумали — "mandatory uglification". Другой источник "красоты" — это поддержка всевозможных экзотических платформ и доисторических версий, из-за чего количество макросов зашкаливает.


                                              И да, читать код стандартной библиотеки просто не надо. Достаточно cppreference.com.

                                              • +1
                                                И настроек компилятора — к слову о _TRY_BEGIN/_CATCH_END
                                                • 0
                                                  можно легко пережить наличие у std::vector приватного метода с названием _M_default_append. Но вот чего понять не могу: зачем аргументы функций-то с __ начинаются?
                                                  • +1

                                                    Чтобы защититься от вещей вроде #define x.


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

                                                    • +2
                                                      Вы даже не представляете, что порой люди пишут:
                                                      #define count int // В фирме Одуванчик принято макросы писать с маленькой буквы
                                                      
                                                      struct vector {
                                                          vector(size_t count); // Боль...
                                                      };
                                                      
                                                      • 0
                                                        зато у вас самая большая база юнит-тестов.
                                                      • 0
                                                        https://habrahabr.ru/company/yandex/blog/323972/#comment_10132820
                                                  • +2

                                                    Его не придётся читать как только добавят концепты в основные компиляторы.
                                                    Помню пытался выяснить почему в GCC STL unordered_map не желает принимать incomplete types при декларации. Так и не понял — адская смесь из разных наследующихся друг от друга и от соседского Шарика классов. И без единого комментария — что особо убивает.

                                                    • +1

                                                      Так это говорит о вашей квалификации, вы не смогли решить задачу, а вместо этого нашли виноватого, библиотеку stl, которую используют миллионы людей

                                                      • 0

                                                        Они страдают молча

                                                        • +5

                                                          Нет, они прочитали документацию на stl, знают для каких задач какой контейнер и просто решают свои задачи. Они не занимаются отладкой stl и не смотрят его код, документации на stl для них достаточно, эти люди очень ценят своё время и заинтересованы не в процессе, а в результате.

                                                          • 0

                                                            Дайте пожалуйста ссылку на место в документации, где сказано про поддержку incomplete types в различных контейнерах.

                                                            • +2
                                                              В стандарте есть:
                                                              An incomplete type T may be used when instantiating forward_list if the allocator satisfies the allocator completeness requirements 17.5.3.5.1

                                                              An incomplete type T may be used when instantiating list if the allocator satisfies the allocator completeness requirements 17.5.3.5.1

                                                              An incomplete type T may be used when instantiating vector if the allocator satisfies the allocator completeness requirements 17.5.3.5.1


                                                              Для map и unordered_map гарантий никаких нет. Если хотите добавить — опишите идею на https://stdcpp.ru/proposals
                                                              • 0

                                                                Спасибо, был не в курсе. К сожалению, честно купленной копии стандарта не имею. А cppreference.com в разделе про unordered_map об этом молчит.

                                                                • +4

                                                                  Вот текущий черновик в удобном для просмотра виде eel.is/c++draft.


                                                                  А вот тут и более старые версии и в виде html, и в pdf.

                                                        • 0

                                                          Я-то задачу решил — использовав обычный мэп. Я про то, что код нынешних реализаций STL крайне тяжело читать. Что является проблемой, когда надо выяснить подробности такого вот implementation-defined behavior. Которым пестрит половина стандарта.

                                                          • 0
                                                            по факту все-таки иногда приходится смотреть в STL.

                                                            пример, возможно, неточный, пару недель назад наткнулся —

                                                            unordered_map<const string, string> прекрасно компилируется в GCC 4.9, но падает с ошибкой в Clang 8 (Apple).

                                                            Из-за разной реализации STL.
                                                      • 0
                                                        те, кто не знает, как должен выглядеть нормальный читаемый код, могут минусовать дальше. я переживу.

                                                        нормальный читаемый код должен выглядеть как JSONNET

                                                    • +1
                                                      Когда я смотрел на код библиотеки std, мне всегда казалось, что его писали инопланетяне.… я никогда не использую в своих проектах код, который выглядит ужасно

                                                      А что вы используете в своих проектах вместо стандартной библиотеки?
                                                      • +1

                                                        @antoshkka когда мне ожидать binutils, сoreutils для C++17?

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

                                                        А что вы используете вместо стандартной библиотеки (вместо std::vector, std::unordered_map и std::string например)?
                                                        • –6

                                                          пишу сам

                                                          • +5
                                                            А можно посмотреть на ваш string?
                                                            • 0

                                                              У меня для вас плохие новости: вам не понравится. Свой string я писал последний раз в 2006. Те, кто минусует, должны еще раз прочитать фразу "в своих проектах". Это не то же самое, что "везде, где только можно".

                                                              • 0

                                                                вот вам string, вот вам парсер xml, вот вам arraylist. Этому коду 10 лет, так не думайте, что сейчас я пишу так же.

                                                                • +2
                                                                  В вашей строке ошибка: если вот тут выскочит исключение, то у вас произойдет double free и приложение рухнет.

                                                                  • +2

                                                                    если выскочит исключение по выделению памяти, то программа так и так не жилец.

                                                                    • +1

                                                                      Совсем нет, не надо распространять вредные мифы.


                                                                      https://www.youtube.com/watch?v=QIiFsqsb9HM

                                                                      • 0

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

                                                                      • 0

                                                                        Ну и приведите мне приложения, где это РЕАЛЬНО обоснованная трата бюджета разработки? Я делал движок для игрушечек, кого волнует его работоспособность в случае, если не хватило памяти?

                                                                        • +3
                                                                          • Браузер и любые документо-ориентированные приложения. Мы можем закрыть один документ или вкладку, но остальные мы хотим сохранить.


                                                                          • Серверные и любые запросо- или транзакционно-ориентированные приложения. Мы выдадим ошибку в ответ на запрос, вызвавший переполнение памяти, и сервер продолжит работать с остальными запросами.

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

                                                                          • +1
                                                                            Собственно мы же вот прям сейчас можем наблюдать, как эту проблему решили крупнейшие производители софта. Они тупо крашат процесс с документом/вкладкой, надеясь что операционка покрашит один процесс, а остальные это не заденет. И делают вид что так и надо.
                                                                          • 0
                                                                            Есть много примеров приложений, которые работают на всём доступном объеме оперативы. Например, компиляторы под плисины.
                                                                            • 0

                                                                              Ну они точно не обрабатывают ошибки выделения памяти в каждом new. Скорее, используют собственные аллокаторы.

                                                                              • 0
                                                                                Простите. А Вы не можете мне в двух словах объяснить, что такое «аллокаторы»? Систематическое изучение C++ у меня впереди, и я понимаю, что аллокаторы — это (наверное) какие специальные функции или конструкции, которые выделяют память. Или… это что-то вроде «умных указателей»? (если попал «пальцем в небо», то не отчаивайтесь, а, просто, расскажите своими словами, будет понятнее, потом, читать книжку, а я Вам «спасибо» скажу)))
                                                                                • 0
                                                                                  1. STL allocators: https://en.wikipedia.org/wiki/Allocator_(C%2B%2B)
                                                                                  2. переопределение operator new/operator delete/operator delete[] с использованием нестандартного менеджера памяти, который работает быстрее за счет увеличения расхода памяти/отказа от многопоточности/использования специфичных для приложения паттернов работы с памятью
                                                                                  3. https://ru.wikipedia.org/wiki/Объектный_пул приложение преаллоцирует возможное количество "тяжелых" объектов и пытается работать с тем, что есть.

                                                                                  В контексте обсуждения, это, скорее, п.3

                                                                    • 0

                                                                      В вашей строке метод format не реентрабельный (им нельзя пользоваться из разных потоков одновременно).

                                                                      • 0

                                                                        я же написал, что вам не понравится. Не было у меня тогда потоков в проекте.

                                                                      • +1
                                                                        А как вы храните в вашем массиве больше int_max элементов, если у вас индексы — знаковые int?
                                                                        • 0

                                                                          очевидно же, что мне это не требовалось

                                                                          • +4
                                                                            В этом и отличие кода стандартной библиотеки от обычного.
                                                                          • +2
                                                                            Очевидно, что ваш код, в отличии от кода стандартной библиотеки, не работает. Понятный неработающий код хуже непонятного работающего.
                                                                            • 0

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

                                                                      • 0

                                                                        а еще есть такое. Это писалось, когда еще не было varidatic templates, не скажу, что это читаемый код, но уровень жести зашкаливает по сравнению с std, где обычный класс std::vector выглядит, как будто по ошибке открыл бинарик.

                                                                        • +1
                                                                          Код stl должен:
                                                                          быть const — корректным
                                                                          быть exception — корректным
                                                                          оптимальным (noexcept, move, минимум аллокаций)
                                                                          устойчивым к #define'ам
                                                                          удовлетворять требования максимальной алгоритмической сложности для всех методов
                                                                          собираться на всех актуальных компиляторах
                                                                          собираться при неполной поддержке стандартов
                                                                          (при работе с памятью) поддерживать кастомные аллокаторы

                                                                          Скольким из этих требований удовлетворяет ваш код?
                                                                          • –2

                                                                            Вы разве не умеете читать? Разве я такое утверждал? Разве я говорил, что мой код идеален и его можно использовать везде? Я лишь сказал, что в своих проектах я не использую код, который выглядит ужасно. И который содержит все эти ИЗЛИШКИ, про которые вы только что написали. В чем я не прав? Что вы мне пытаетесь доказать? То, что я и без вас знаю?

                                                                            • +5
                                                                              Скорее всего, подспудно, Вам пытаются донести мысль, что нужно во всём проявлять профессионализм. Если Вы опускаете планку где-то «для себя», то, скорее всего, будете опускать её и «для других». Сие уже настораживает. Как минимум.
                                                                            • 0
                                                                              А у меня к Вам немного перпендикулярный вопрос: обязаны ли мы пользоваться шаблонами?

                                                                              Да, шаблоны предоставляют возможность записать решение задачи в общем виде. Но является ли этот подход единственным для реализации стандартной библиотеки? И, конечно, очень важно понять, что должно быть частью языка, а что должно, действительно, быть реализовано в виде библиотеки. Шаблоны занимают здесь некое промежуточное положение: «ни нашим, ни вашим». Между тем, хотелось бы иметь явную поддержку со стороны языка, чтобы семантика выражений всегда гарантировала определённый результат, а программист мог бы выбирать как модель памяти, так и набор используемых им алгоритмов.
                                                                              • 0
                                                                                Но является ли этот подход единственным для реализации стандартной библиотеки?

                                                                                Нет, если тянуть информацию о типах в рантайм или писать на макросах.

                                                                                Между тем, хотелось бы иметь явную поддержку со стороны языка

                                                                                поддержку чего?

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

                                                                                а можно пример, где это не выполняется и где стандарт не помечает поведение как id/ub? Sequence points, емнип, в процессе, можете о них не упоминать

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

                                                                                Модель памяти можно выбирать — используем свои аллокаторы. Какие алгоритмы вы имеете в виду?
                                                                                • 0
                                                                                  Хорошо. А можно узнать, что такое
                                                                                  std::vector
                                                                                  — это шаблон или это встроенный тип? Дело в том, что от языка программирования ожидаешь, что в нём самом реализованы основные вычислительные концепции. Кажется, что так должно быть. Или, например, сортировка.Сортировка, как таковая, единственна, но есть множество алгоритмов сортировки. Что с этим делать? В STL мы, просто, вызваем нужный нам алгоритм и всё, так? А если мы хотим иметь пул методов и выбирать по ситуации, какой лучше? По моему, это — увод мною разговора в другую сторону, но я ещё подумаю, что именно меня интересует.

                                                                                  P.S. Ещё вспоминаю Borland C++ 5.0, где, вроде бы, были всякие контейнеры, но без шаблонов. Чем так страшно предоставление информации о типах в рантайме? И что будет, если попробовать разобраться в различных способах построения контейнерных типов? Вряд ли такой способ единственен…
                                                                                  • 0
                                                                                    Вы задаете вопросы, которые отлично разобраны в книге «Дизайн и эволюция языка C++». Пытаться отвечать вам здесь — это как пытаться пересказать изрядную часть этой книги своими словами.
                                                                                    • 0
                                                                                      «Дизайн и эволюция языка C++», говорите? О, это, как раз, то, что мне нужно. Буду читать с карандашом в руках. :-)
                                                                                      • 0
                                                                                        Кстати, а никто не пытался? Это мог быть целый цикл статей на Хабрахабре! Я видел только пару-тройку кратких обзоров.
                                                                                      • 0
                                                                                        Хорошо. А можно узнать, что такое
                                                                                        std::vector
                                                                                        — это шаблон или это встроенный тип?

                                                                                        есть простое эмпирическое правило. Видите std:: и не знаете что это — см. документацию.

                                                                                        Сортировка, как таковая, единственна, но есть множество алгоритмов сортировки.

                                                                                        Вам стандарт дает гарантию, что std::sort выполнится за
                                                                                        O(N·log(N)), where N = std::distance(first, last) comparisons.
                                                                                        (since C++11)

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

                                                                                        P.S. Ещё вспоминаю Borland C++ 5.0, где, вроде бы, были всякие контейнеры, но без шаблонов. Чем так страшно предоставление информации о типах в рантайме?

                                                                                        производительность ниже в несколько раз
                                                                                        • 0

                                                                                          Вообще говоря, для некоторых частных случаев, быстрее придумали.
                                                                                          (Есть алгоритмы сортировки быстрее встроенной в ст. библиотеку).
                                                                                          Например, поразрядная сортировка N K-битных чисел работает
                                                                                          за O(NK), вместо O(NK log(N)) при использовании std::sort().


                                                                                          Но согласен, что надо просто улучшать библиотеку, чтобы она сама выбирала
                                                                                          лучший вариант.

                                                                                          • 0
                                                                                            Не существует алгоритмов, основанных на сравнении элементов, которые могут гарантировать меньшее, чем (n*logn) колличество сравнений. Это математически невозможно.

                                                                                            Radix sort работает только с данным, которым можно 1 в 1 поставить в соответствие положительное целое число. И в большинстве реальных ситуаций проигрывает quicksort или heapsort как по скорости, как и по памяти.
                                                                                            • 0
                                                                                              Не существует алгоритмов, основанных на сравнении элементов, которые могут гарантировать меньшее, чем (n*logn) колличество сравнений. Это математически невозможно.

                                                                                              И как это противоречит моему комментарию?

                                                                                              • 0
                                                                                                Никак. Я и не говорил, что вы не правы.
                                                                                          • 0
                                                                                            Я подозреваю, что сложность выполнения алгоритмов — вещь довольно теоретическая. Практически, мы имеем дело с конкретными реализациями, и реальная быстрота выполнения алгоритма может весьма варьироваться. Обычно, в таких случаях, ориентируются на систему статистических испытаний. Не говоря, уж, о том, что, в зависимости от типов данных и от размеров данных будут существенно меняться и скорость выполнения операций, а это значит, что говорить о самом быстром алгоритме не приходиться. Все эти теоретические оценки асимптотические. Вот почему, реальное программирование — это искусство выбора оптимального решения в данных обстоятельствах. А, поскольку, каждый запуск приложения происходит в уникальных обстоятельствах, то и от приложения следует ожидать возможности выбирать различные пути реализации одной и той же операции. Вот я о чём.
                                                                              • 0
                                                                                На эту тему мне очень нравится эпическая драма в двух частях от Dr. Dobbs,
                                                                                C++ and The Perils of Double-Checked Locking: Part I
                                                                                C++ and The Perils of Double-Checked Locking: Part II
                                                                                В которой рассматривается написание потокобезопасеного велосинглтона на С++

                                                                                Хотя в С++11 нам упростили жизнь.
                                                                          • +3

                                                                            Кстати, а чем не устроил uint8_t из cstdint? И ещё — понятно, что таких случаев уже не найти, но обычно полагают что байт всё-таки может быть не восьмибитным на некоторых платформах; std::byte будет гарантировать 8, или он тоже будет формально назван платформенно-зависимым?

                                                                            • +1
                                                                              а чем не устроил uint8_t из cstdint

                                                                              Тем что это unsigned char и соответственно is_same<uint8_t, unsigned char>::value == true.

                                                                              И да, байт может быть не восьмибитным, и такие машины еще есть и работают. В std::byte столько же бит сколько бит в байте на целевой машине.
                                                                              • 0
                                                                                Но тогда и в unsigned char не 8 бит? В этом случае is_same снова true?
                                                                                • +2
                                                                                  is_same сравнивает типы а не их размер.
                                                                                  std::is_same<int, int>::value                 // true
                                                                                  std::is_same<int, unsigned int>::value        // false
                                                                                  std::is_same<int, signed int>::value          // true
                                                                                  std::is_same<std::byte, char>::value          // false
                                                                                  std::is_same<std::byte, unsigned char>::value // false
                                                                                  std::is_same<std::byte, signed char>::value   // false
                                                                                  

                                                                                  std::byte — это отдельный не арифметический тип данных.
                                                                                  • 0
                                                                                    Я знаю. Хорошо, переформулирую вопрос. На машинах со словом не равным 8 битам (я просто не знаю, простите) uint8_t тоже эквивалентен unsigned char?
                                                                                    • +3
                                                                                      Зависит от платформы.

                                                                                      Скорее всего на такой платформе не будет uint8_t, uint16_t, uint32_t, uint64_t. Стандарт С++ говорит что эти алиасы — опциональные.
                                                                                      • 0
                                                                                        В архитектуре NeuroMatrix sizeof(char) == sizeof(short) == sizeof(int). 32-битный байт во всей красе. Таким образом там char и short являются синонимами обычного int.
                                                                                        • +5
                                                                                          О, кстати об интах с размером. Можно сделать в будущих стандартах как-нибудь так, чтобы uint_fast8_t вёл себя как int, а не как char, и
                                                                                          uint_fast8_t num = 17; 
                                                                                          std::cout << num << std::endl;
                                                                                          не приводило к консольному апокалипсису?
                                                                                          • +2
                                                                                            Хороший вопрос. Попробуем решить.
                                                                                        • 0
                                                                                          TI TMS320 с размером байта 16 бит, uint8_t в stdint.h отсутствует. Думаю в cstdint его тоже не будет.
                                                                                          • 0
                                                                                            Ясно, спасибо.
                                                                                            • 0
                                                                                              Тоже натыкался на техасовские процы (какой-то из C54xx) и байтовые проблемы: memcpy копирует не по одному байту, а по два, и соответственно размер в нее надо передавать sizeof(var)/2.
                                                                                              • 0

                                                                                                Странно, потому что sizeof обязан выдавать размер в char, то есть в данном случае в 16-битных словах, а не в байтах. На TMS320C40 например, все типы 32-разрядные, sizeof(char) == 1 но CHAR_BITS == 32

                                                                                                • 0
                                                                                                  Скорее всего вы правы, сейчас уже трудно вспомнить. Возможно я использовал именованную константу и потом делил её, что бы не перетереть память.
                                                                                            • 0
                                                                                              Есть такая штука, что например uint8_t* нельзя алиасить к другим указателям.

                                                                                              https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66110
                                                                                              • 0
                                                                                                Чаще всего «слово» на машинах равно 16 битам. На x86 так точно
                                                                                              • 0
                                                                                                Тогда объясните в каких именно случаях предполагается использовать std::byte, а в каких unsigned char.
                                                                                                • 0
                                                                                                  Когда вы хотите хранить массив двоичных данных, имеет смысл использовать byte хотя бы чтобы показать другим что вы храните именно двоичные данные.
                                                                                              • 0
                                                                                                сначала unsigned char не 8 бит. в C byte определяется как unsigned char. так что правильней всегда думать, что байт — это unsigned char, а не пакет из 8-ми бит. на целевой платформе это может быть и 16 бит, и 11 и неизвестно ещё сколько. конкретные биты, их номера, упоминаются уже в ветвях #ifdef… #else… #endif, при реализации работы с битами для конкретных платформ.
                                                                                              • 0
                                                                                                А std::byte* можно будет алиасить с другими типами указателей?
                                                                                                • 0
                                                                                                  Да. Для std::byte* те же правила по алиасингу, что и для unsigned char.
                                                                                            • 0
                                                                                              При инициализации std::function знак «равно» тоже можно не писать?
                                                                                              • 0
                                                                                                Да, но придется написать скобки
                                                                                                std::function   d{ [](int i) { std::cout << i; } };
                                                                                                // или
                                                                                                std::function   d( [](int i) { std::cout << i; } );
                                                                                                
                                                                                                • 0
                                                                                                  Ну, я это и имел в виду ,)
                                                                                                  • 0

                                                                                                    А эта красота работает только для нескольких стандартных классов? Или пользовательские тоже смогут?

                                                                                                    • 0
                                                                                                      Работает и для пользовательских. При том из коробки, если шаблонные параметры класса участвуют в конструкторе. Иначе придётся писать explicit deduction guide.
                                                                                                • 0

                                                                                                  Миленько, да. А что выбросили?

                                                                                                  • +4
                                                                                                    Весь заголовочный файл <codecvt> помечен как устаревший. В нём находилась вот это:
                                                                                                    namespace std {
                                                                                                      enum codecvt_mode {
                                                                                                        consume_header = 4,
                                                                                                        generate_header = 2,
                                                                                                        little_endian = 1
                                                                                                      };
                                                                                                    
                                                                                                      template<class Elem, unsigned long Maxcode = 0x10ffff,
                                                                                                        codecvt_mode Mode = (codecvt_mode)0>
                                                                                                      class codecvt_utf8
                                                                                                        : public codecvt<Elem, char, mbstate_t> {
                                                                                                      public:
                                                                                                        explicit codecvt_utf8(size_t refs = 0);
                                                                                                        ~codecvt_utf8();
                                                                                                      };
                                                                                                    
                                                                                                      template<class Elem, unsigned long Maxcode = 0x10ffff,
                                                                                                        codecvt_mode Mode = (codecvt_mode)0>
                                                                                                      class codecvt_utf16
                                                                                                        : public codecvt<Elem, char, mbstate_t> {
                                                                                                      public:
                                                                                                        explicit codecvt_utf16(size_t refs = 0);
                                                                                                        ~codecvt_utf16();
                                                                                                      };
                                                                                                    
                                                                                                      template<class Elem, unsigned long Maxcode = 0x10ffff,
                                                                                                        codecvt_mode Mode = (codecvt_mode)0>
                                                                                                      class codecvt_utf8_utf16
                                                                                                        : public codecvt<Elem, char, mbstate_t> {
                                                                                                      public:
                                                                                                        explicit codecvt_utf8_utf16(size_t refs = 0);
                                                                                                        ~codecvt_utf8_utf16();
                                                                                                      };
                                                                                                    }
                                                                                                    
                                                                                                  • 0
                                                                                                    я тихонько мечтаю о некоторых фичах С++, которые никогда не появятся.
                                                                                                    Что это могло быть?
                                                                                                    1) полноценные модули (видел в обсуждениях)
                                                                                                    2) библиотека модулей (вытекает из первого). сейчас приходится рыскать на просторах интернета и перебирать библиотеки от посторонних авторов на посторонних ресурсах. Хотя в С++20 заявляны, возможно, некоторые классы. Побольше их на все случаи жизни.
                                                                                                    3) функции типа GetHelpFunction(), которая предоставит инфу по функционалу. Желательно, на универсальном языке, понятном человеку. И тут возникает проблема — пока универсального языка не существует, есть варианты костылирования из уже существующих языков, типа того же английского (недостаток — его надо знать заранее и хорошо).

                                                                                                    Поставил сверхсложные задачи (особенно третью). Т.к. я технарь, сложностей не боюсь — уже продумываю решение проблемы. Вариант универсального языка:
                                                                                                    обучение в играх. Там вообще может не использоваться текст, только жесты и демонстрация к чему жест приводит. Чем не универсальный язык? Но он реализуется, скорее, средствами IDE, нежели средствами самого языка программирования. Но при таком подходе от текстового языка программирования можно отказаться (он используется, но не виден пользователю).
                                                                                                    • 0
                                                                                                      И тут возникает проблема — пока универсального языка не существует, есть варианты костылирования из уже существующих языков, типа того же английского (недостаток — его надо знать заранее и хорошо).

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

                                                                                                      И еще не совсем понятно, что «хуже»: какие-то знания, или обучение.
                                                                                                      • +5

                                                                                                        Под библиотекой модулей — вы подразумеваете пакетный менеджер, по типу npm, pip, nuget итп? Если да, то я просто мечтаю о такой фиче. Реализуется сейчас частично отдельными независимыми разработчиками инструментов, так, например, в VS есть "NuGet для C++"


                                                                                                        Последнее непонятно, зачем функция справки на уровне языка?


                                                                                                        На мой взгляд самый логичный вариант — использование метаданных, как в C#, с описанием функции, аргументов итп. На английском.

                                                                                                        • 0
                                                                                                          Я начал сейчас ковырять conan, пока очень доволен, но он еще молод и активно развиваться. https://www.conan.io/
                                                                                                          • 0
                                                                                                            Проблема conan-ов, vcpkg, CPM и др. подобных вещей в том, что им требуется централизованный репозиторий пакетов или репозиторий с метаописаниями пакетов. В условиях, когда нет одного доминирующего де-факто стандарта на управление зависимостями это неудобно. Плюс к тому, на Linux-ах разработчики используют зачастую штатные менеджеры пакетов и в сторону внешних инструментов, вроде conan-а или cpm-а смотрят неодобрительно.

                                                                                                            Имхо, удобнее, когда управление зависимостями делается без необходимости куда-то загружать пакет или его описание. Например, когда зависимости разруливаются через ExternalProject_Add в CMake. Но только в более человеческом виде :) Используем нечто подобное уже около года — очень удобно, по крайней мере для подключения OpenSource проектов, которые можно забирать с github, bitbucket или sourceforge.
                                                                                                        • 0

                                                                                                          В других языках проблема c документацией решена: javadoc

                                                                                                        • 0
                                                                                                          А всякие ifstream с wstring и раньше же работали?
                                                                                                          • +3

                                                                                                            Это было нестандартное расширение в MS STL

                                                                                                            • –2
                                                                                                              А остальным и не нужны недокидорвки, т.к. есть UTF-8
                                                                                                              • 0

                                                                                                                Проблема в том, что стандарт С++ не говорит о том, в какой кодировке однобайтовые строки. И не говорит, как нижележащее системное АПИ должно их интерпретировать. Современные линуксы используют UTF-8, там всё просто. А Windows использует однобайтовую системную локаль, с непредсказуемым результатом.

                                                                                                          • +1

                                                                                                            Куча всего по constexpr вводят, даже обсуждают constexpr аллокации в куче. А хорошего метода для отладки шаблонного кода (constexpr кода в чуть меньшей степени) нету, помимо топорного static_assert и type_traits (хорошо, что ещё появился if constexpr).


                                                                                                            Было бы здорово, если бы появилось что-то по типу static_warning. Оно, в сочетании с будущим $reflect (который, насколько я знаю, будет способен вытащить имя типа с присутствующими квалификаторами) могло бы чуточку поспособить отладке и пониманию кода, который разворачивается в момент компиляции.

                                                                                                            • 0
                                                                                                              Приходите на встречу. Как раз буду рассказывать о планах на constexpr_trace и constexpr_assert для С++20.
                                                                                                              • +1
                                                                                                                запись будет?
                                                                                                                • 0
                                                                                                                  Да. Но не уверен что будет способ задавать вопросы удалённо.
                                                                                                                  • 0

                                                                                                                    А можно ли оставлять вопросы на сайте?

                                                                                                                    • 0
                                                                                                                      Мне тут nataliamakarova773 подсказала, что «на youtube можно будет задавать вопросы, будем озвучивать докладчикам».
                                                                                                                • +2

                                                                                                                  Концепты с двусторонними последствиями (т.е. бьют по рукам и вызывающий код, и за непредусмотренный юз в теле ф-ции). Мечты, мечты...

                                                                                                                  • 0
                                                                                                                    Бьёрн говорил, что пока отказались из-за проблем с совместимостью.
                                                                                                              • 0
                                                                                                                Долго гуглил, но так и не смог понять: какой из вариантов корутин обсуждается? Было два: бустовый и microsoft'овский, и точно были холивары, который лучше и правильнее. Будут у нас слова co_async, co_await или нет?
                                                                                                                • +5
                                                                                                                  «Гор-рутины» как бы намекают :)
                                                                                                                • +1
                                                                                                                  Спасибо большое за огромную проделанную Вами работу!

                                                                                                                  Вопрос насчёт Number TS: правильно ли я понимаю, что мы будем иметь эффективную длинную арифметику из коробки?
                                                                                                                • 0
                                                                                                                  Используете ли вы в компании, или в своих личных проектах, плагины/динамическую-загрузку-библиотек? Опишите в комментариях, какими функциями и классами вы для этого пользуетесь?

                                                                                                                  Да, используем. В проекте плагинная система построена на базе CTK Plugin Framework.