Pull to refresh

Comments 224

Есть новости, когда планируется отказаться от хэдеров и препроцессора?
Нужно чтобы все проекты переехали на модули, тогда и можно будет отказываться (другими словами — не раньше C++35)
UFO just landed and posted this here
Расскажите поподробнее про аллокатор. Чем он хорош?
UFO just landed and posted this here
UFO just landed and posted this here
Коментарий на «придумать то, чего в принципе не придумано, но кому-то хорошо было бы иметь»?

ОК, когда-нибудь попробую реализовать в Boost.
UFO just landed and posted this here
Пишите детальное предложение, кажется что в ваши идеи стоит показать комитету.
UFO just landed and posted this here
Без макросов некоторые вещи не делаются, когда будут делаться, тогда и можно отказываться. Вещи, связанные с удобным для программиста генерированием повторяющегося исходного кода.
Интересно, а идей улучшить препроцессор вместо того что бы хаить макросы не возникало?
А как именно вы предлагаете его улучшить?

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

А расскажите поподробнее, как вы видите подобные макросы в C++?
вы пропустили важную деталь:
А расскажите поподробнее, как вы видите подобные макросы в C++?

т.е. без конфликтующего синтаксиса, breaking changes и чтобы был прок

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

ок, сделать допустим можно. Нужно ли? Для большинства случаев шаблонов более чем достаточно, а с появлением концептов не хуже ни синтаксис, ни гарантии. То, что на шаблонах сейчас сделать сложно или нельзя, будет рефлексия. Для случаев, связанных с условной компиляцией (дебажная информация, юнит-тесты и пр.) эти гигиенические макросы всё равно будут полагаться на сырые макросы флагов компиляции. Для остального (документация, например) требуется не столько поддержка от компилятора, сколько от системы сборки.
То что я выше посмотрел по ссылке, не рефлексию больше напоминает, а generator expressions, которые позволяют ast менять, очень для метаклассов будут полезны. Но это точно не C++23, как Саттер сказал. Может быть какой-то TS к 26 году разве что.
Это всё опять же «такое себе решение».Нужно элементарное: больше базового синтаксиса на этапе компиляции тогда и макросы станут не нужны.

Вот, например, я хочу написать один шаблон с большим количеством кода, но обрабатывающий либо 1 элемент без списка либо множество элементов из списка и функция обхода элементов списка сама по себе сложная. Так вот макросом или внутренними директивами компилятора я могу не плодить адовую копипасту, а вот на C++ даже с шаблонами и последним стандартом до сих пор не могу, точнее могу могу но костыли, вроде, sfinae не выглядят решением ибо это костыли, ужасные костыли, а я хочу писать, примерно так:
<typename T>
... some_func(..., T x, ...)
...
if (exist(x.getList))
{
... код который даже не скомпилируется без метода getList у типа T
}
...
...

Всё упирается в элементарное if этапа компиляции которое могло бы выключить кусок функции если у нас в классе есть метод для получения одного элемента и нет метода для получения коллекции.

P.S. в идеале хотелось бы даже шаблон не создавать, но это уже совсем мечты.
Так уже можно:
template <class T>
concept Listable = requires(T x) {
     x.getList();
};

<typename T>
... some_func(..., T x, ...)
...
if constexpr(Listable<T>)
{
... код который даже не скомпилируется без метода getList у типа T
}
...
...
О, через concept уже лучше и не столь вырвиглазно, благодарю, жаль пока не завезли много где, да и опять же требуется писать много дополнительного кода, как с sfinae. А теперь смотрим на элегантные средства некоторых компиляторов (__if_exists/__if_not_exists Statement) и плачем поскольку средства очевидные, не требуют лишнего кода, работают везде, а не только в шаблонах, очень давно реализованы и это в чистом виде реализуемо как синтаксический сахар :'(

// the__if_exists_statement.cpp  
// compile with: /EHsc  
#include <iostream>  
  
template<typename T>  
class X : public T {  
public:  
   void Dump() {  
      std::cout << "In X<T>::Dump()" << std::endl;  
  
      __if_exists(T::Dump) {  
         T::Dump();  
      }  
  
      __if_not_exists(T::Dump) {  
         std::cout << "T::Dump does not exist" << std::endl;  
      }  
   }     
};  
  
class A {  
public:  
   void Dump() {  
      std::cout << "In A::Dump()" << std::endl;  
   }  
};  
  
class B {};  
  
bool g_bFlag = true;  
  
class C {  
public:  
   void f(int);  
   void f(double);  
};  
  
int main() {   
   X<A> x1;  
   X<B> x2;  
  
   x1.Dump();  
   x2.Dump();  
  
   __if_exists(::g_bFlag) {  
      std::cout << "g_bFlag = " << g_bFlag << std::endl;  
   }  
  
   __if_exists(C::f) {  
      std::cout << "C::f exists" << std::endl;  
   }  
  
   return 0;  
}  

Вот именно такое я хочу в стандарте, но даже в 20 этого не будет. Такую замену макросов хочется ^_^
Всё в ваших руках! Пишите предложение на подобный функционал, с формальностями поможем.
Идея MS хорошая, но недостаточно гибкая: она проверяет только наличие соответствующего идентификатора, но не его свойства, например, различные перегрузки.

А вот чего не хватает концептам, так это ключевого слова `implements` (как в Java/C#), чтобы контроль можно было осуществлять при определении сущности, а не при её использовании.
важно как правило не то, есть ли Foo::bar, а есть ли метод Foo::bar, принимающий Args… и возвращающий T
UFO just landed and posted this here
UFO just landed and posted this here
Ооо, благодарю, это уже похоже на «код здорового человека».
Вещи, связанные с удобным для программиста генерированием повторяющегося исходного кода.

Можете привести пример кода, который невозможно сгенерировать с помощью шаблонов и constexpr?

Регулярное выражение?
А как их можно макросами реализовать?
Плюсовыми — никак. А вот с макросами вроде Rust-овских или Nermele-овых вполне себе.
github.com/hanickadot/compile-time-regular-expressions
Так затем в рантайме все равно приходится работать со string-view и формировать из результатов разбора нужные значения.

Вот на продвинутых макросах (или на D-шных CTFE+mixin), гипотетически, можно получить что-то вроде:
auto [year, month, day] = $super-puper-macro("^(?<year:short>[0-9]{4})/(?<month:byte>[0-9]{1,2}+)/(?<day:byte>[0-9]{1,2}+)$").match(s)

где year будет иметь тип int, а month и day — тип byte.
Какой-нибудь кейс когда проще написать макрос нежели шаблон/функцию для регулярки?
if( error ) return error;
и прочие модификации control-flow?
Конкатенация строк в названиях переменных?
Не вижу в этом ничего хорошего. Код пишется один раз, зато читается постоянно. Упрощение написания кода ценой усложнения его чтения и отладки — это выстрел в ногу.
Вы просили пример — я его привел :) Я не говорю, что это хорошо, но на шаблонах и лямбдах так не сделать.
UFO just landed and posted this here
Можете привести пример кода, который невозможно сгенерировать с помощью шаблонов и constexpr?

#define LIST(F)F(int,a)F(bool,b)F(char,c)F(string,d)
struct t_foo{
  #define F(TYPE,NAME)TYPE NAME;
  LIST(F)
  #undef F
  void use_func1(){
    #define F(TYPE,NAME)::func1(#TYPE,this->NAME);
    LIST(F)
    #undef F
  }
  void use_func2(){
    #define F(TYPE,NAME)::func2(#TYPE,this->NAME,#NAME);
    LIST(F)
    #undef F
  }
};
#undef LIST
Спасибо, хороший пример, что отсутствие рефлексии в C++ — это плохо. Но альтернатива с variadic templates и string literals таки возможна:
habr.com/post/243581
По ссылке не альтернатива, а тонны нечитаемого кода. Минусы у макросов в том что они трудно поддерживаемы и очень неудобно их отлаживать если их использовать как генераторы кода, но если их использовать только для простых вещей, например банальная генерация пары public get/set и private члена, то их, к сожалению, просто нечем заменить в С++, вообще нечем.
А какие-нибудь замены макросам __FILE__, __LINE__ уже придумали?
От препроцессора отказаться невозможно в принципе, т.к. без условной компиляции не обойтись. Но я бы хотел, чтобы действие директив препроцессора ограничивалось только одним файлом. Именно файлом, а не translation unit.

UFO just landed and posted this here
Нет, не позволяет — обе ветки должны компилироваться.
UFO just landed and posted this here
Вот не надо вот от препроцессора отказываться. Это ещё более замедлит принятие С++ на всяких микроконтроллерах и SoC, где до сих пор пишут на С образца семьдесят лохматого года.
пишущие на си образца семидесятых годов заведомо не аудитория новых стандартов с++
Знакомые программисты микроконтроллеров говорили, что не используют плюсы из-за слишком толстой стандартной либы.
Это заблуждение или как говорят, ваши коллеги скорее всего не умеют готовить embedded проекты на С++.
Стандартная либа в таких проектах обычно не используется, а вот все плюшки языка доступны
Рекомендую показать вашим знакомым consteval-функции C++.

В комитете присутствующие embedded разработчики были вне себя от радости. Теперь можно легко заставлять компилятор вычислять что-то только на этапе компиляции, без попадания этого в рантайм.
Это очень опасное заблуждение, более того C++ компилятор генерирует гораздо более качественный ассемблерный код, умеет в разы лучше оптимизировать и даже линкует большие проекты быстрее поскольку C++ знает гораздо больше о коде чем C.
Что там за опасное заблуждение, простите? Комментатор вам сказал «станадртная либа жирная для embedded» — это никто оспаривать не будет, даже члены комитета С++. Почему вы пытаетесь что-то другое в комменте видеть?
Из-за того что обработка исключений генерирует code-bloat, и появился
www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0709r0.pdf
очередной метод обработки ошибок. С текущей реализацией STL под bare metal очень и очень слабо юзабелен.

Я сам мудохался с тем чтобы под вполне себе комфортные 8мб на плюсах писать. Да, в итоге все же остановился на коде с поддержкой исключений, но какие же они жирные…
Опасное заблуждение в том, что из-за std они не используют плюсы вообще. Но кто мешает писать свои классы с noexcept или просто писать очевидный код? Кто мешает использовать noexcept реализации. Да и вообще из личных примеров я месяца три назад просто пересобрал «драйвер» для Ethernet контроллера для одной ужасной железки как C++ код убрав директивы и он стал работать быстрее и стал более cache friendly вот просто так, без изменений кода. Без C++ я банально не могу писать в том же Embedded удобные вещи.
Нет, помимо std там там есть и концептуальные проблемы.
Dan Saks потрясающее видео на эту тему сделал:
www.youtube.com/watch?v=D7Sd8A6_fYU
Можно сколько угодно распинаться о преимуществах С++, усилия будут тщетны, пока разработчик на С не будет слышать то что лично ЕМУ нужно.
ембед сишники вообще народ сложный. Основных аргумента против плюсов у них три: «stl не влазит в контроллер» (ты и на си им пользоваться не сможешь), «исключения раздувают код» (noexcept или выключи их), «шаблоны раздувают код» (при этом заменяют шаблоны макросами, которые так же инстанцируются по месту и раздувают код точно не меньше). Так что им нужно то? Даже designated initializers уже завезли. Это слабо похоже на взвешенную гражданскую позицию.
Ну а что плюсы могут дать эмбеду, если stl не брать, шаблоны не использовать, исключения отключить? Много вы тех же плюсовых либ, допустим, в таких условиях скомпилите? А сишные либы у них и без этого геморроя работают.
Классы? Деструкторы им, как правило, не нужны, потому что память чаще всего статически выделяется. Две с половиной виртуальных функции можно и руками вызвать через указатели или switch. Писать аргумент, передаваемый в местном аналоге ECX, они привыкли справа от названия функции, а не слева, так что синтаксический сахар тоже мимо.
Ну то есть какие-то преимущества у плюсов есть, но ни одной киллер-фичи конкретно для эмбеда нет. При том что плюсы намного, НАМНОГО сложнее как язык.
Если вы выкинете из C++ все, что перечислили, то оставшийся язык будет не сложнее C. И писать на нем будет так же убого и грустно, как и на C. Хотя останутся еще такие приятные вещи, как ссылки, перегрузки функций и большая типобезопасность.

Но вот с какого перепугу вы решили отказаться от шаблонов и классов? Про их оверхэд можете рассказать?
Ну там выше пишут, что «шаблоны раздувают код», не я придумал.
А еще там пишут вот что:
«шаблоны раздувают код» (при этом заменяют шаблоны макросами, которые так же инстанцируются по месту и раздувают код точно не меньше).
Но это вы почему-то игнорируете.
Вот честно, шаблоны — это одна из самых сложных штук в плюсах. Первые 10 лет её вообще никто не понимал, вместо stl все юзали свои велосипеды на виртуальных функциях. Макросы тоже не сахар, но в них рядовому быдлокодеру не надо «понимать», ими можно просто пользоваться.
Первые 10 лет её вообще никто не понимал
Отучаемся говорить за всех. И про понимание, и про юзание велосипедов с виртуальными функциями.

В 90-е с шаблонами главная проблема была в том, что не во всех компиляторах они поддерживались. Я, например, начал использовать шаблоны где-то с 1995-го. Но года до 1998-го или даже до 2000-го приходилось оглядываться на компиляторы, в которых шаблонов не было вообще.
я выше давал ссылку на доклад
code::dive conference 2015 — Bartosz Szurgot — C++ vs C the embedded perspective

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

  • RAII (да, даже в embedded надо порой чистить ресурсы)
  • constexpr и conseval
  • алгоритмы ( и их можно взять из STL, они на исключения и RTTI не завязаны, кроме пары исключений)
  • constexpr и consteval
  • ООП (да, внезапно c ООП код получается более читаемый)
  • Ссылки
  • Type safety
  • Частичное невелирование проблем а аслиасингом — большая производительность и меньший по размеру код
  • ??? (наверняка что-то забыл)
Давайте только честно.

RAII — отличная концепция… для языка с исключениями, но без finally. Так-то ресурсы можно и в процедурном стиле почистить.
Когда в эмбед завезут constexpr и особенно consteval — ещё неизвестно, а макросы вот они тут.
Алгоритмы — это книжка Кормена сотоварищи.
В ООП стиле можно писать и на С (про сахар см. выше замечание про расположение аргумента this).
Type safety сводится к тому, что у вас есть три с половиной типа: int, int*, (int*)() и иногда struct*. Структуры дадены системными библиотеками и железом, и прикрутиться к ним с этими вашими классами не так-то просто.
Отсутствие ссылок компенсируется тем, что nullptr указывает на вполне себе доступную область памяти.
Ну в общем всё перечисленное это клёво, модно, молодёжно, но киллер-фичей не является (кроме м.б. consteval и таки алгоритмов).
RAII — отличная концепция… для языка с исключениями, но без finally. Так-то ресурсы можно и в процедурном стиле почистить.

Алгоритмы — это книжка Кормена сотоварищи

зачем делать 100 раз то, что можно сделать (как правило, сделали за тебя) единожды?

Когда в эмбед завезут constexpr и особенно consteval — ещё неизвестно, а макросы вот они тут.

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

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

их можно обернуть и забыть о том, что это сырые структуры

Отсутствие ссылок компенсируется тем, что nullptr указывает на вполне себе доступную область памяти.

по стандарту nullptr (в отличие от NULL) может указывать только на заведомо недоступную область памяти
зачем делать 100 раз то, что можно сделать (как правило, сделали за тебя) единожды?

Далеко не все алгоритмы работают со статическими массивами языка С. А всякие сбалансированные деревья стиральной машине не нужны.
берем обычный gcc, ставим таргетом контроллер, получаем с++17 уже сегодня.

Грустное ха-ха три раза. ДАЖЕ если gcc знает целевой машинный код (что не факт), это ещё ничего не значит. Потому что набор железа, конфигурация памяти, соглашение о вызовах, нестандартная линковка, системные либы на несовместимом с GCC диалекте — всё это превращает затею в скачку по граблям. Как правило, у вас есть компилятор от производителя, который принимает «что-то похожее на Си», а всё остальное от лешего.
их можно обернуть и забыть о том, что это сырые структуры

Дети, не слушайте дядю, он говорит глупости.
В классе, обёрнутом вокруг системной структуры, вы:
1. не можете использовать наследование
2. не можете использовать полиморфизм, ни виртуальный, ни просто перегрузку
3. инкапсуляцию использовать можете, но это вам ничего не даст
4. не можете использовать деструкторы
5. и final у вас тоже нет, не завезли.

Поясняю.
Допустим, вы воткнули в класс-обёртку виртуальную функцию.
Это значит, что перед структурой появился указатель vptr на таблицу виртуальных функций.
Системные либы про него ничего не знают, и тупо копируют память без вашего vptr.
В итоге вам рано или поздно вернут объект, у которого мусор вместо vptr (и об этом никто не знает). Пояснять, чем закончится вызов метода?
Что хуже, вы можете даже не понять, что у вас появился vptr. Это может быть перегруженная внешняя функция, например. В двух вариантах, с конверсией типа аргумента и без. Возможно шаблонная, да. Просто заинклюдили header-only библиотечку и ага.
С дополнительными полями аналогично, только растут они в памяти сверху, а не снизу. Но точно также могут потеряться внутри системы, или вы можете затереть память, выделенную системой.
Теперь допустим вы огородили поля данных модификатором private, нагородили геттеры-сеттеры и добавили в них логику. И до кучи влепили деструктор.
Беда в том, что системные либы не знают про ваши сеттеры и деструкторы. Т.е. они в ваших тестах вызываются, а в процессе прохождения через либу — нет. Счастливой отладки!
по стандарту nullptr (в отличие от NULL) может указывать только на заведомо недоступную область памяти

Ага, ага, по стандарту.
Допустим, у вас всего 256 байт (не мега- и не кило, просто байт) ОЗУ. Как думаете, можно ли читать адрес 0х00?
> Дети, не слушайте дядю, он говорит глупости.

Кажется другой дядя не умеет в ООП. Прятать стрёмные системные вызовы за красивыми интерфейсом весьма просто.
Было:
int fd = open("light_device");
light_settings s{0xf1, 100};
ioctl(fd, SET_LIGHT, &s);
close(fd);

Стало:
Light lamp("light_device");
lamp.set(Green, 10_kHz);

Виртуальными функциями и правда не воспользовались… Если у вас в руках молоток, это не значит что всё вокруг становится гвоздями.
Да-да, вот вам не успел ответить. Расскажите про строчку close(fd).
Вот допустим, что в 99% случаев мне нужно зажечь лампочку в одном месте (допустим, сейчас), а погасить в непредсказуемом другом. По асинхронному таймеру, или если юзер нажмёт кнопку, или (здесь большой список или).
Зачитайте, пожалуйста, все преимущества RAII и ООП в обозначенном мной случае.
Расскажите про строчку close(fd).
Вы сперва расскажите как в вашем гипотетическом сценарии будете передавать fd из места, где вызвали open() в место, где вы хотите вызвать close().

Поскольку вам привели самодостаточный пример. Вы его пытаетесь во что-то преобразовать, но не показываете во что именно.
fd будет глобальной статической переменной. Да-да, я знаю, сейчас меня закидают помидорами и скажут ффуу, но это самый экономный способ.
Дальше она равна 0 если файл закрыт или не 0 если открыт. Проблем с гонками сигнала нет, т.к. можно безопасно закрывать закрытый или даже некорректный номер файла.
fd будет глобальной статической переменной.
А теперь представьте, что у вас lamp будет глобальной переменной.

При этом, представьте, у вас может быть шаблонный класс Light, который настраивается политикой поведения: RAII или не RAII. Например, у вас может быть:
static Light<NO_RAII> red_lamp;
...
void turn_on() {
   red_lamp.open("/device/red_lamp");
   red_lamp.on();
   Light<RAII> green_lamp{"/device/green_lamp", Light<RAII>::on};
   ...
}
void shutdown() {
  if(red_lamp.is_on()) {
    red_lamp.off();
    red_lamp.close();
  }
  ...
}

И для red_lamp у вас не будет ни конструктора, ни деструктора. А для green_lamp будет и то, и другое. При этом накладные расходы будут такие же, как случае, если бы вы все это реализовывали ручками на чистом C.
Move семантика вам поможет с владением. См. примеры ASIO например.

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

«со статическими массивами языка С» работают std::begin/std::end, возвращающие достаточно для передачи в любой алгоритм. Проблемы могут быть разве что с std::sort, выделяющим память

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

тогда и вопрос не стоит. Мы же всё-таки говорим о тех случаях, когда можно использовать с++ вместо си.

Поясняю.
Допустим, вы воткнули в класс-обёртку виртуальную функцию.
Это значит, что перед структурой появился указатель vptr на таблицу виртуальных функций.
Системные либы про него ничего не знают, и тупо копируют память без вашего vptr.

я вас здесь остановлю и приведу минимальный пример, демонстрирующий где вы неправы: при касте указателя на наследник к указателю на базовый класс адрес может меняться, и он будет указывать на корректный инстанс базового класса. А если «системная либа» вдруг лезет в память вокруг переданного ей объекта, в ней UB

Да и оборачивать надо с умом. Например, можно не наследованием, а композицией. По-хорошему, небезопасные сишные кишки в плюсовом коде лучше полностью обернуть, от греха подальше. Благо обычно это можно сделать без оверхеда.
«со статическими массивами языка С» работают std::begin/std::end

Да?! Ну вот у меня есть указатель wtf*, поясните, как будет работать std::end.
при касте указателя на наследник к указателю на базовый класс адрес может меняться, и он будет указывать на корректный инстанс базового класса

простите, вы не понимаете, как работает С++. Указатель на инстанс будет корректный, но только, ещё раз подчеркну, только с точки зрения конкретного компилятора С++.
А если «системная либа» вдруг лезет в память вокруг переданного ей объекта, в ней UB

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

Не например, а единственный рабочий вариант. Только оверхед получается немаленький. Проще node.js воткнуть например.

Да?! Ну вот у меня есть указатель wtf*, поясните, как будет работать std::end.

статический массив языка си, о котором шла речь, это не wtf*. Впрочем, указатель является корректным random access итератором. begin =wtf, end = wtf + size. Вы же знаете размер статического массива?

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

Нет, с системной либой всё ок, это у вас в плюсовой программе будет даже не UB, а просто баг.

А можете привести пример? Пока что я не в состоянии интерпретировать ваши утверждения из предположения что вы правы

Не например, а единственный рабочий вариант. Только оверхед получается немаленький. Проще node.js воткнуть например.

компиляторы с++ ныне более чем способны справиться с инлайнингом пары функций
UFO just landed and posted this here
для языка с исключениями, но без finally.
Внезапно, RAII помогает и для обычного случая return, и для обычного break.

А про finally. Его что, уже в стандарт C завезли?
Type safety сводится к тому, что
у вас void* не будет автоматически каститься к чему угодно.
> Type safety сводится к тому, что у вас есть три с половиной типа

Вот вам типичный код на embedded:
set_light(LIGHT_GREEN, 10);

Читается как-то не очень, а ещё оба параметра на вход имеют тип int. Ошибиться крайне легко.

А вот как это можно написать в C++
set_light(Green, 10_kHz);

Получается намного читаемее, да и компилятор не даст вам перепутать порядок аргументов:
enum Color: unsigned short { Red = 0x1, Green = 0xF1, };
enum Frequency: unsigned {};
constexpr Frequency operator"" _kHz(unsigned val);


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

Поддерживаю antoshkka хотя бы в том, что С++ компилятор может дать большую типобезопасность без увеличения размера выходного кода (даже с отключенными исключениями и RAII).

Может быть, вышеприведенные примеры и не убедят закоренелого сишника, но по крайней мере помогут человеку, который уже знаком с обоими языками, и думает на чем писать проект под embedded — на C или на урезанном C++.
Ну а что плюсы могут дать эмбеду, если stl не брать, шаблоны не использовать, исключения отключить?

из stl всё еще остается хороший пласт header-only библиотек/классов, навскидку алгоритмы, утилитарные классы аля tuple/pair/variant/optional/bitset, более широкая и консистентная мат. библиотека. И не забывайте про фичи самого языка — всякие range-based for, constexpr, лямбды, перегрузки, инициализация по умолчанию. Опять же, шаблоны могут многое из того чего не умеют макросы

Классы? Деструкторы им, как правило, не нужны, потому что память чаще всего статически выделяется

и вдруг возникают сценарии типа «вот здесь на входе подними бит, а на выходе опусти», в которых RAII превосходно себя показывает

Ну то есть какие-то преимущества у плюсов есть, но ни одной киллер-фичи конкретно для эмбеда нет

Например, типобезопасность — нет нужды постоянно кастить указатели из/в void*/char*. Это дает компилятору/анализатору больше информации о данных и позволяет лучше диагностировать ошибки и оптимизировать.

При том что плюсы намного, НАМНОГО сложнее как язык.

но писать на них код во столько же раз проще, на подмножестве языка едва превосходящим по объему си.
«Концепция C с классами уже решает» тьму проблем, например для работы с очередью, которая оперируют своим типом на указателях можно удобно использовать методы класса, не тащить в явном виде указатель на очередь, а главное не размазывать код работы с очередью по проекту.
ембед сишники вообще народ сложный.

А ещё очень многие не осилили, притом не только C++, но и C до конца, у них «компилятор код ломает» поэтому они дебаг вместо релиза собирают, а читать про volatile им также лень как и C++ изучать.
Не могу найти на фотке автора ranges. Где радостный Эрик?! =)
Сидит почти что в центре фотографии. Но на фото не попал Кейси Картер — второй по величине вкладчик в Ranges :(
А Рядом с ним Гор Нишанов?
Ага. Если хотите — могу выложить фотографию в оригинальном разрешении. Там больше лиц видно, и даже меня можно разглядеть в зеркале :)
Меня мучит вопрос, может кто подскажет: в бустовом variant и optional есть поддержка ссылок, в std их нет. Я читал, что это из-за неопределенности оператора присваивания. Но может стоило все-таки пойти по пути буста? Мне лично очень часто нужна опциональная ссылка, да и вариант со ссылкой тоже. Почему приняли именно такое решение, которое (кажется, сильно) ограничивает сферу примененя этих типов?
Ссылки напрямую не поддерживаются, но всегда можно написать std::variant от std::reference_wrapper и получить поведение близкое к Boost.

А проблему вы верно указали — поведение std::varaint<int, int&> при присваиваниях будет определяться внутренним содержимым. Это показалось странноватым комитету, и решили не поощрять подобное и не переусложнять класс variant. Те кому всё же нужно подобное поведение всегда могут воспользоваться reference_wrapper
Может кто-нибудь разъяснить что значит dynamic_cast внутри constexpr-выражения? Как это вообще понимать?
А в чём проблема? Известен тип и значение аргумента, можно вычислить результат. Если такое приведение невозможно, результатом будет nullptr.
Тогда получается, что это просто static_cast, который возвращает nullptr в случае неудачи, так?
Да. Ну и вам будет проще переносить имеющийся код на constexpr — dynamic_cast будет просто работать, не надо будет их заменять на странные конструкции с std::is_constant_evaluated.
Фух, понял! Благодарствую, а то с утра не отпускало:)

(Плюсануть не могу, неполноправный.)
Если мы создаем переменную в constexpr контексте, то компилятор об этой переменной должен всё знать, включая её внутреннее представление и базовые классы.

И соответственно, раз компилятор о ней всё знает, то он может и отслеживать тип переменной, даже если она передаётся по ссылкам на базовый класс. Ну а раз так, то почему бы не разрешить ему и dynamic_cast делать:

struct base {
    constexpr virtual ~base() = default;
};

struct forty_two: public base {
    constexpr int say_42() const { return 42; }
};

constexpr int try_say(const base& b) {
    forty_two* p = dynamic_cast<forty_two*>(&base);
    if (p) {
        return p->say_42();
    }

    return 0;
}

constexpr void do_something() {
    constexpr forty_two ft{};
    static_assert(try_say(ft) == 42);
}
Ага, понятнее, спасибо! А в случае, если переменная создана не в constexpr-контексте, тогда и функция перестанет быть constexpr, так?
Да, всё верно. Функция будет выполняться на рантайме. Или будет ошибка компиляции если попробуете использовать эту функция в том месте, где компилятор требует вычисление на этапе компиляции:

void do_something() {
    /*constexpr*/ forty_two ft{};

    // Следующая строчка не соберётся. Компилятор будет жаловаться,
    // что переменная `ft` не известна на этапе компиляции и он не может
    // выполнить `try_say` как constexpr функцию.
    static_assert(try_say(ft) == 42); 
}
А как там с исключениями в constexpr-выражениях? Ну тоесть если try/catch есть — то все понятно, а если нет? Или если есть дальнейший проброс исключения? Что будет? Ну тоесть, понятно, что в итоге все должно свестись к ошибки компиляции, но вот сам вид этой ошибки не очень понятен.
Кидать исключения в constexpr по прежнему нельзя. Если при constexpr вычислении будет выполнена строчка с throw — компиляция прервётся и будет выведено сообщение об ошибке.
Ага, понятно, спасибо, про бросать — понятно.
А про не ловить? Вот если в вашем примере заменить dynamic_cast с указателей, на ссылки и приводить не к тому типу, да еще и try/catch-ем не обложить, что будет?
Или dynamic_cast на ссылках нужно обязательно заварачивать в try/catch блок, при чем в месте вызова?
Если dynamic_cast захочет кинуть исключение в constexpr, то будет ошбка компиляции, и никакие catch(...) не помогут.

По сути все идет к тому что в каждом компиляторе C++ будет встроенный интерпретатор C++. Интересный путь развития…

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

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

Мне кажется, Вы говорите про Common Lisp :)
Можно посмотреть на механизм текстовых mixin-ов из D. Там можно вызвать CTFE функцию (compile-time function evaluation, аналог плюсовых constexpr/consteval), которая возвращает строку. Строка скармливается конструкции mixin. Компилятор берет эту строку как подлежащий разбору и обработке исходный код.

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

Но есть и проблема, как говорят D-шники: если в mixin отдали сгенерированный в compile-time текстовый фрагмент, например, такого вида:
class Generated {
  void f() {...}
  void g() {...}
}
а потом в программе написали:
auto obj = new Generated;
obj.g();

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

В C++ часть того, что можно делать на текстовых mixin-ах из D, может стать доступной через метаклассы. Но, наверное, не все.
Не откроет ли это ящик Пандоры?
Всенепременно откроет (если уже не открыли, с тьюринг-полными шаблонами). Но тем
интереснее:)
Ох, eval()-а нам только и не хватало.
Возникли подозрения, что дизайн можно улучшить, используя последние новинки C++20 (в основном концепты, и немного ranges).
Так автор Networking вроде на cppcon об этом прямо говорил, что «ребейзить» надо.
О! А можно ссылочку на видео, а то я найти не могу :(
www.youtube.com/watch?v=hdRpCo94_C4 (да, это не автор TS)
вот это вроде, долго чет искал) Таймкод с пруфом про «надо ребейзить» не подскажу. Если я ошибся, то может и не это видео вовсе. Извините в случае чего.
А про алгебраические типы данных и паттерн-матчинг что-нибудь известно? Вроде как перед этой встречей появилось несколько конкурирующих предложений на эту тему.
До их рассмотрения дело не дошло. Зато успели немного пообсуждать монадические интерфейсы для std::optional.
До их рассмотрения дело не дошло.
Жаль. Видимо, придется ждать C++23 или даже C++26.
Зато успели немного пообсуждать монадические интерфейсы для std::optional.
Дурное дело не хитрое.

Шутка :)
Можете вкратце описать результаты обсуждения? Было бы очень интересно увидеть когда-нибудь что-то такое.
Обсуждали предложение P0798. В отсновном выбирали имя для функции map/transform и определялись с требованиями к аргументам данной функции. В C++20 попасть скорее всего не успеет.
UFO just landed and posted this here
а можно поподробнее про
// Следующие две строчки могут пагубно повлиять на рассудок:
assert(c_auto[4] == 11); // не константно
assert(c_auto[5] == 11); // константно

из примера про is_constant_evaluated? Почему так?

Может ли к с++20 constexpr приехать в математические функции стандартной библиотеки? Просто глупо получается, что после всех притянутых в стандарт constexpr-фич попытка буквально «что-нибудь посчитать на этапе компиляции» спотыкается об какой-нибудь std::sin
Математические функции уже почти сделали constexpr, я надеюсь что успеется к C++20. LEWG одобрила бумагу https://wg21.link/P0533, осталось пройти всего одну группу.

Основная проблема — это имплементация. У GCC всё хорошо в этом месте, а вот Clang не может воспользоваться библиотекой от GCC для математических вычислений на этапе компиляции — лицензия не позволяет. А написать подобную библиотеку самим — это огромные трудозатраты (приблизительно сотня или тысяча человеколет).

Так что когда примут в стандарт, некоторые компиляторы часть функций не смогут сделать constexpr в течение длительного времени.
Про странный пример… Всё сводится к вычислению вот этих двух строчек с переменной `in` известной только на рантайме:
    const int v_runtime0 = __builtin_is_constant_evaluated() ? in : 11;
    const int v_runtime1 = __builtin_is_constant_evaluated() ? 11 : in;


Так вот, если для v_runtime0 функция is_constant_evaluated вернёт true, то получится что v_runtime0 надо подсчитать константно с помощью рантайм переменной. Это что-то невозможное, поэтому тут возвращается false.

Для v_runtime1 если функция is_constant_evaluated вернёт true, то никаких противоречий нет и можно подсчитать константно.

Как справедливо заметили в чатике t.me/ProCxx, решать надо как в загадках про лжеца: «могло быть в первом ответ y? нет, потому что было бы противоречие».
К C++20 многие (и я в их числе) хотят увидеть в стандарте контейнеры, которыми можно пользоваться на этапе компиляции.

А можно юзкейсов немного? А то я пока даже в принципе не понимаю зачем нужны constexpr. constexpr контейнеры же для меня вообще rocket-science какой-то.
Самый ожидаемый мной контейнер — constexpr std::string. За счёт того, что компилятор сможет создавать такую строчку на этапе компиляции, иницилизация в следующем коде перестанет быть динамической и станет статической:
void foo() {
    static const std::string date_time_fmt = "DATE: YYYY MM DD TIME: BLA-BLA";
}

Другими словами, вся инициализация будет происходить на этапе компиляции, и при первом заходе в функцию не будет залочиваться мьютекс (или ещё как-то потоко-безопасно инициализироваться статическая переменная), не будет динамически выделяться память…

Весь код с статическими/глобальными строковыми переменными станет работать немного быстрее.

Другой практический пример — это constexpr std::unordered_map. Можно будет делать подобие switch по строкам.

Любителям метапрограммирования с constexpr std::vector откроются новые возможности. Так например подобное нечитаемое безобразие просто не надо будет писать, так как можно будет обойтись std::vector и алгоритмами из стандартной библиотеки. Метапрограмный код получится читаемый, а не тот что мы имеем в C++14/17.

Ну и наконец — без constexpr контейнеров не сделать рефлексию, а её очень хотят успеть к C++23.
Любителям метапрограммирования с constexpr std::vector откроются новые возможности. Так например подобное нечитаемое безобразие просто не надо будет писать, так как можно будет обойтись std::vector и алгоритмами из стандартной библиотеки. Метапрограмный код получится читаемый, а не тот что мы имеем в C++14/17.


Не является ли данный пример типичным местом применения для gsl::span?
Кстати, как дела у std::array_view, всё заглохло?
constexpr строки и вектора это оч хорошо (вью же не сложишь), но на моей практике многое делается уже c одним gsl::span (хотя я знаю у себя место где constexpr вектор бы упростил код)

Upd: а, там массив возвращается; ну да, вектор полезен был бы
А чем не вариант для константных строк использовать string_view? Если она инициализируется литералом, время жизни обеспечено. Можно даже отнаследовать какой нибудь literal_view с constexpr конструктором из массива char.
Для константных — самое то. Но вот выше люди коментируют, что хотят макросами имена функций и переменных генерировать. Для того чтобы это можно было делать через рефлексию, а не макросы, нужен constexpr string.
constexpr нужны для манипуляциями над данными в RO памяти, которых в программах может быть достаточно много. Например, у нас есть массив, данные в котором мы ищем по индексу. Как не нафакапить при заполнении массива и не промахнуться с индексом? Очень просто, написать constexpr функцию, проверяющую валидность массива и вызвать её из static_assert.

А теперь допустим мы ходим искать в этом массиве не по индексу, а по содержимому.
Сделаем constexpr хэшмапу и будем искать за (примерно) константное время. Впрочем, этот велосипед был скорее на поиграться с возможностями нового с++; в мире розовых поней я лучше подожду constexpr std::unordered_map.
Всё очень круто! Но будет ли помещаться С++20 в голову разработчику?
Нужен новый Майерс, раз уж старый Майерс завязал с объяснениями хитростей С++!
Для этого даже создали отдельную подгруппу в комитете :-) Если у Вас есть идеи, как можно помочь — то добро пожаловать :)
Но будет ли помещаться С++20 в голову разработчику?
В мою и C++98 не помещался. Но, как показала практика, если ты не разрабатываешь компилятор C++ или стандартную библиотеку для C++, то знать _весь_ C++ и не нужно.
Уверяю вас, вы не одиноки!
Но будет ли помещаться С++20 в голову разработчику?


Большинство стандартных библиотек современных языков программирования не помещаются в голову разработчику: Java, C#, C++, Python…

Я немного не следил за событиями: в других языках тоже жалуются?
А как поживает constexpr с восклицательным знаком?
Это же упомянутый consteval? Или что-то ещё?
Да, проморгал. Спасибо!
Слава богу, решили выпилить этот восклицательный знак, фуф.
Ну там и доллар из метаклассов и рефлексии выпилили.
И это проморгал :( Ссылку можно?
Спасибо!

old: $class M 
new: constexpr void M(meta::type target, const meta::type source)


Ммда, ну, поживем-увидим.
Это еще что. Там на проперти вообще ужас какой-то. (то что в целом метаклассы превращаются в эдакие функции, я не вижу плохого, но надеюсь синтаксис еще доработают. Саттер тоже не в восторге).
Интересно было бы услышать тех, кто 2D графику в опросе выбрал — как вы будете это использовать, для чего? Использовать стандартную библиотеку без какого-либо графического фреймворка?
Рисовать таблицы, графики, обрабатывать изображения, простейший GUI (да, без фреймворка). Лично мне сильно не хватает изкоробочной возможности отрисовать картинку со статистикой и отдать её пользователю как веб страницу.
Вы мимо, но спасибо)

отрисовать картинку со статистикой и отдать её пользователю

Ну пользователю-то картинку и пожать придется? я почитал
www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0267r7.pdf
там же рендеринг только.
Не будут же туда еще видео кодеки пихать)
Там есть сохранение в формате изображений (PNG и JPEG точно были).
Да, я виноват, просмотрел, 13.9 раздел, если кому интересно.
В такой постановке, согласен, может быть полезно для минималистичного взаимодействия. Все равно меня немного напрягает «внешняя зависимость» в виде PNG кодеков в стандартной библиотеке, и как это все будет специфицировано (с учетом того что периодически всплывают уязвимости в libpng той же).
В юникоде, стандартной библиотеке и demanglingе тоже уязвимости всплавают. Пока всё норм.
то есть подтянуть внутрь стандартной библиотеки libpng/libbmp/libsvg? Или в каком виде отрисовывать? Почему не скомпилировать это wasm и рисовать в канвас из локального фреймбуффера если это веб?

То есть Cairo в стандарте не смущает (а это и есть пропозал), а libpng смущает?)

Смущает. Все серьезные приложения (вроде браузеров) уже переехали на Skia, а тут стандартизацию Cairo ещё только обсуждают.

Смущает. Хотя наверное было бы неплохо иметь некоторый кроссплатформенный интерфейс для кодеров/декодеров изображений и аудио до кучи. Но это не раст с его типажами, поэтому довольно сомнительно все это.
А как в раст подобные типажи помогут?
В раст можно прокинуть некоторый интерфейс графики который реализовать отдельными крейтами. Но тут же возникает зачем оно в стандартной библиотеке. Да и боли с рисованием там тоже особо нет.
А зачем это в стандарной библиотеке?
Чтобы можно было пользоваться, а не страдать. Networking, std::thread, Filesystem служат той же цели (впрочем как и вся стандартная библиотека).
С++ нужна не раздутая стандартная библиотека, а нормальный репозиторий для всего этого хозяйства.
C++ в первую очередь нужна функциональная стандартная библиотека.
Согласен, но может это хотя бы сделают на откуп вендорам, как было со стандартизацией больших интов и GC? просто например какой-нибудь вендор под embedded может и не захотеть реализовать стандарт под свою железку. (хотя чего я, как будто бы сегодня их заставляют реализовывать весь стандарт).
Сейчас наоборот идёт движение в сторону того, чтобы явно разметить в стандартной библиотеке embedded/freestanding части. Тоесть выделить некое подмножество стандартной библиотеки, которое работает на любой платформе, даже на такой где нет оперативной памяти, файловой системы и проч.
Ееее! Это очень крутое движение, рад был про это слышать (удивительно как я такое пропустил).
Networking, std::thread, Filesystem

Это всё следствия бетонирования POSIX. А графический стек везде разный и меняется постоянно, чтобы соответвовать новым ускорителям и железкам. Ваша библиотека морально устареет раньше, чем её успеют стандартизировать.

Я не специалист в 2D графике, но насколько мне известно основные принципы отрисовки за последние 30 лет не менялись. Применяешь к холсту примитивы, говоришь отрисовать, готово.

Поправьте меня если я не прав.
2D графика в последнее время очень не сильно изменилась по той простой причине, что это простой подход, но упершийся в потолок развития. Императивный подход (а-ля, нарисуй круг, линию, потом дугу) весьма тормозной, гораздо производительнее использовать 3Д библиотеки и рисовать ими 2D.
Или, с другой стороны, дальнейшее развитие 2D рисования — это выкинуть текущее АПИ в помойку и сделать новое с нуля; что и происходит (но только в 3D) — Vulkan, Metal
А как поживает P0631R0? Появится ли наконец-то в С++20 стандартная константа для числа Пи? Или так и будем 4*atan(1)?
Что-то мне не очень понятна ситуация c [[visible]]:
www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0276r0.html
и
www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1283r0.html

Пусть у нас в хедер файле

[[shared]] void library_foo();

Когда мы его подключаем из реализации, считается, что мы делаем экспорт.
Когда включаем это объявление, и реализации нет — считаем что импортируем из библиотеки.
Теперь вопрос, а если у нас этот же хедер используется для статической библиотеки? тут уже без макроса не обойтись, верно? Иначе использующий API код не сможет определить, что ему там вставлять, обычную слабую ссылку или импорт (в MSVC там будут отличаться имена символов ж).
отдельные аттрибуты для импорта/экспорта — чисто msvc-шная проблема и если они её решат, то лучше будет всем.
Дело не в отдельный аттрибутах (я про них не упоминал). Уверен, разработчики смогут справиться. Речь о том что разные имена в ABI, и это не покрыть фичами языка (либо создавать новый ABI которым никто не будет пользоваться).
причем тут msvc под linux тоже пользуются visibility — экспортируешь символ — default, по умолчанию hidden
по умолчанию в visibility значение (внезапно) default — экспортировать/импортировать символ
Язык без «изкоробочной» поддержки UTF-8 в 2020 году это провал, ребята.
Если комитет этого не понимает, то анонсированного выше в комментариях С++35 просто не будет.
C++ это такой язык, что даже не будь изкоробочной поддержки в стандартной библиотеке чего угодно, это бы не привело его к провалу.
Существующая практика такова, что почти всегда для реализации нужных функций нужны сторонние библиотеки.

Посмотрите на Boost.Text, может вам понравится:
www.youtube.com/watch?v=944GjKxwMBo

p.s. я даже не буду комментировать «провал» языка который живет 30 лет и загибаться не планирует.
Чувствую себя агрессивным проповедником в чужой церкви, но блин, коллеги, давайте смотреть правде в лицо.
Что у нас было 20 лет назад? Был STL, которым никто не пользовался, даже самыми базовыми вещами. Все юзали те же строки и массивы или в стиле С, или CString/CArray, или свои велосипеды. При этом CString уже поддерживал (тогдашний) юникод. Однако С++ являлся топовым универсальным языком, на котором писали всё — от системных утилит до фронтенда.
Прошло 20 лет, строки С++ всё ещё не поддерживают юникод.
Ну ок, фронтенд потерян безвозвратно. Весь бизнес-приклад давно переехал на java/.net. Как и 90% кода операционных систем. Бэкенд, всякие веб-сервисы, отжали пых и руби. Новые системные тулзы пишут на расте или го, не на плюсах. Наука со своим матаном переехала на питон. Геймдев ещё держится, но с этими вашими смартфонами и там уже не всё гладко.
Может С++ загибаться и не планирует, но по факту он уже сегодня воспринимается ближе к фортрану или коболу, чем к промышленному языку.
Простите, не хотел никого обидеть.
Хм… я пишу это сообщение из браузера написанного на C++, используя операционку у которой пользовательские библиотеки почти все на C++, собранную компилятором написанном на C++… разработчики которого играют в игры, написанные на C++ :)

… при этом работаю в фирме, где «бизнес приклад» написан на C++, и даже веб сервисы написаны на C++.

За всю науку говорить не могу, но в CERN бозон хиггса искали используя плюсы (и Boost), в ИММ РАН физические задачи решают на C/C++/Fortran… да и в МГУ тоже физики используют C++.

Что-то в ваших показаниях не сходится.
Был STL, которым никто не пользовался, даже самыми базовыми вещами.
Вы вот как-то с ходу начали оперировать ошибочными постулатами. Я, например, один из тех, кто начал использовать STL еще до принятия C++98. Тогда по рукам ходила реализация STL от Rogue Wave, кажется, которую можно было скотчем и спичками прицепить к Watcom C++, Borland C++. А в 1998-ом в Visual Studio 6.0 STL уже был из коробки, хотя и не стандартный еще.

Так что вы уже со своим тезисом «никто не пользовался» не правы. Ну и дальше, если копнуть, везде такая же история.
Ребят, да я про тенденцию говорю. Тогда на плюсах писали реально всё, из конкурентов был или чистый Си или Паскаль/Дельфи.
Сейчас мы ниши перечисляем. Вот мол у автора статьи ОСь и браузер написаны на плюсах. А у меня ось на джаве, а браузер потихоньку на раст переписывают.
Если бы лямбды, auto и нормальный for появились на 10 лет раньше, этого бы не было.
А у меня ось на джаве
Это какая?
Если бы лямбды, auto и нормальный for появились на 10 лет раньше, этого бы не было.
Да ладно, устойчивая тенденция миграции с C++ на Java началась где-то в 2000-ом или 2001-ом. К 2004-ому она уже была вполне себе четкой. И Java тогдашняя по выразительности с C++98 не могла соревноваться.

Зато она была безопасной, со сборкой мусора, большим JDK. И даже умудрялась не так уж и сильно тормозить на тогдашней технике.

За прошедшие 15 лет C++ уже вытеснили из тех ниш, где его выгодно было заменить на Java, C#, Scala и пр. Но там, где он остался и применяется сейчас только Rust и, отчасти, Go может что-то предложить. Да и тому же Rust-у еще экосистему свою вырастить нужно. А то что ни растоман, то и жалоба, что Qt у них нет.
Это какая?

Ведроид жи ну. Да-да, я знаю, что там внутре у ней неонка, в смысле линукс, но он тоже не на плюсах написан.
У Андроида практически весь userspace написан на C++, включая линкер.
Ну так не на Java же OS написана. Пока. Вроде как Google хочет со временем на Фуксию перевести, которая уже на плюсах пишется.
ОС это не только и не столько ядро. Это библиотеки, утилиты, планировщики, рюшечки, окошечки и прочие пакетные менеджеры. Посмотрите на зоопарк дистрибутивов Линукса — перевести прод с условной федоры на убунту не сильно проще, чем с винды (из-за чего всякие докеры и появились).
Возврат гугла к плюсам обусловлен, в первую очередь, тем, что у самой java проблем выше крыши, причём как технических, так и юридических и организационных. Ну и да, здесь надо похвалить комитет, плюсы сейчас развиваются действительно поживее, чем java.
Это библиотеки, утилиты, планировщики
И вот это все на C или C++.
рюшечки, окошечки и прочие пакетные менеджеры
А это уже относится к ОС, если под ОС понимать что-то вроде Windows. А вот в том же Linux-е есть сама ОС и есть Desktop Environment. Вот окошечки-рюшечки — это про Desktop Environment, а не про ОС.
Слышал что уже длительное время идёт обратная миграция. Процессоры почти перестали расти в тактовой частоте и в основном растут в количестве ядер. Ну и тут grabage collector начинает играть злую шутку: если у вас 1 ядро, и GC отрабатывает за 1мс, то вы теряете 1мс процессорного времени; если у вас 16 ядер, и GC отрабатывает за 1мс, то вы теряете 16мс процессорного времени. Альтернативные подходы к GC обладают аналогичными недостатками.
Слышал что уже длительное время идёт обратная миграция.
Да тут сложно оценки сделать. С одной стороны — да, есть прецеденты, когда с Java переходят на C++ (или используют в Java код на плюсах через JNI). С другой стороны, на Java и C# делают тот же самый HFT, где плюсам самое место (и где они хорошо себя чувствуют).
А можно ткнуть пальцем, где HFT на шарпах/java пишут? Я пониаю когда околовычислительне всякие микросервисы, графики рисовать, отчеты пилить, но вот чтобы прям непосрдественно общение трейдеров — не сышал.
Наверное, самый известный — это Lmax со своим Disruptor-ом.

Несколько лет назад здесь, на Хабре было интервью с Романом Елизаровым, он там рассказывал про разработки трейдинговой системы на Java. Там же есть ссылка на OpenHFT.

Про разработку на C# в обсуждении на RSDN-е кто-то рассказывал (отсюда и далее вниз по ветке).
давайте перефразируем: раньше выбора не было, а сейчас он появился. Раньше железо не позволяло лишний раз писать на джаве/диезе/питоне, а сейчас позволяет. То, что появилась достойная альтернатива в виде раста — хорошо, но едва ли в ближайшем будущем все забросят свои кодобазы и сбегут на него. У плюсов есть старые детские проблемы, и это не значит что их не надо (или нельзя) поправить
Понимаете, если комитет до сих пор спорит, не пора ли в языке сделать, наконец, строки с поддержкой юникода, то конкурировать такой язык будет, как заметил antoshkka, разве что с фортраном за умы седовласых академиков.
Комитет не спорит на тему «надо ли», комитет обсуждает как это сделать правильно. Если вы знаете как это делать правильно — то пишите proposal, вас с радостью выслушают.

P.S.: А передёргивать слова некрасиво, я такого не говорил.
(Пример про ИММ РАН разве не вы предложили?)
Примеры передёргивания:
1) Java иногда используются для студенческих курсовых. Жаль, ведь получается что этот язык — лишь удел недоучек.
2) Андроид использует Java. Не спроста vanxant утверждает что данная ОС — удел разработчиков недоучек.

Тут приличное общество, давайте не будем опускаться в дискуссиях до подобных приёмов.
предложите навскидку zero-overhead юникод библиотеку
А нету таких. Переход на юникод это боль и страдания. Питон страдал несколько лет, php до сих пор страдает с mbstring и func_overload, и так далее. Но вариантов нет, мир уже чуть больше, чем горстка юзеров в англоязычных странах.
Комитет на то и нужен, чтобы изучить ошибки других, сжать тестикулы в кулак, принять решение и добровольно-принудительно перейти всем сообществом. А не как у нас в плюсах принято, что в языке несколько видов строк, несколько видов «умных» указателей, а к четырём одновременно существующим видам обработки ошибок предлагается добавить ещё столько же. Берёшь либу и не знаешь, что от неё ожидать.
Есть, в конце концов, буст, где можно обкатать потенциальных кандидатов «в живой природе» до их стандартизации.
А можно ссылку на историю о страданиях питона? Я думал его изначально с поддержкой делали.
Строки в Питоне стали юникодовыми только с третьей версии. И это сломало обратную совместимость.
«Берёшь либу и не знаешь, что от неё ожидать»
Пока для меня, основная боль как разработчика, это не то что в С++ нет какой-то там поддержки utf-8, а то что сторонние кроссплатформенные C библиотеки просто используют fopen/stat и т.п. которые разумеется на Win работают, но без поддержки юникода.
— ffmpeg/vidstab
— opencv — весь файловый api
— glog
— dlib
(первое что за минуту в голову пришло, тысячи их)
Да, патчи-то наложить недолго, но е-ёмое, не понимаю я разработчиков библиотек, под винду эти функции существуют два десятка лет, вы делаете «кросплатформенность» и забиваете на поддержку юникода в FS? что с вами не так?
MS, сделайте уже поддержку setlocale(«utf-8»), чтобы fopen работал как везде, это не лечится)
With insider build 17035 and the April 2018 update (nominal build 17134) for Windows 10, a «Beta: Use Unicode UTF-8 for worldwide language support» checkbox appeared for setting the locale code page to UTF-8.[a] This allows for calling «narrow» functions, including fopen and SetWindowTextA, with UTF-8 strings. Microsoft claims this option might break some functions (a possible example is _mbsrev) as they were written to assume multibyte encodings used no more than 2 bytes per character, thus until now code pages with more bytes such as GB 18030 (cp54936) and UTF-8 could not be set as the locale.

Но походу сделано как я понимаю криво, настройка — глобальная общесистемная, выбирается юзером, никакой не setlocale(«utf-8»).
А можно показать такие системы у которых 90% кода написаны на .net/java?
Наука со своим матаном переехала на питон
только частично. Вычислительные ядра все на плюсах (если поновее) или вообще на fortran. Ну и много чего на CUDA/OpenCL.
Ну ок, фронтенд потерян безвозвратно.

А Qt'шники то и не в курсе. Во многих фронтендных задачах нужно лишь выводить текст, а для этого можно и std::string как контейнер использовать.

Раньше у нас были char, signed char, unsigned char, wchar_t, int8_t, uint8_t, теперь ещё char8_t появился. Как-то уж слишком много сущностей, полоснуть бы бритвой Оккама по ним.
char = текст ASCII
chat8_t = code unit из UTF-8
int8_t, uint8_t = целые числа
std::byte = неизвестные данные (не текст и не числа)
wchar_t = системный тип символа (привет, ужасы кодировок Windows)
signed char, unsigned char = что угодно в устаревшем коде; стоило бы выпилить
Интересно, когда все эти радости начнут поддерживать популярные компиляторы. Судя по поддержке С++11/14/17 как раз где-то к 2023 году. А до этого останется только обсуждать все это в блогах. И ведь еще дожить надо.
Вы неправы. Начиная с С++14, поддержка максимум на год задерживалась. Другое дело, что если концепты вы можете начать использовать сразу после появления их поддержки в тулчейне, то вот с модулями не все так просто) минимум ждать поддержки и в системах сборки, а максимум — во всех используемых вами библиотеках.
Ну вот сейчас 2018 год, С++17 полностью (по крайней мере на словах) 3 популярных компилятора поддерживают. У нас все проекты собираются с флагами 17 стандарта.

Благодаря регулярным и предсказуемым релизам, разработчики компиляторов могут как раз быстрее реализовывать фичи. Т.е. в 2019 заморозят набор фич, и к 20 году большая часть в том или ином виде будет реализована со спец флагами в компиляторах. Для концептов, контрактов и модулей, кстати, флажки или экспериментальные ветки уже есть.
С++17 полностью (по крайней мере на словах) 3 популярных компилятора поддерживают.

Как там поживает <memory_resource>? А < execution >?

А вот тут речь уже о том что фичи стандартной библиотки тянутся медленнее)
Компилятор — «да! да здравствует новый стандарт!», его реализация STL — «подождите, пожалуйста помедленнее, я запсваю» =)
Если не брать штуки по constexpr — то большая часть мажорных нововведений как раз по части компилятора, я думаю с ними проблем не возникнет.

в любом случае, согласитесь, что 5% отдельных фич, с которыми проблемы, это не та вещь про которую можно ныть «ой беда, 10 лет теперь стандарт реализовывать будут».
Как не показалось это странным, но memory_resource и execution есть в VC++ :)
std::assume_aligned выглядит как какой-то крайне частный случай.
Во современных компиляторах есть __assume(condition) или __builtin_unreachable, при помощи которых можно сообщать оптимизатору любую доп. информацию. Вместо того, чтобы вводить специальную функцию только для выравнивания, лучше было стандартизовать функцию assume и дать рекомендации по тому, как с её помощью можно описывать выравнивание.
Аналог assume в C++20 есть, см контракты.
Судя по описанию, контракты — это просто ещё один вариант assert. Не могу найти информации, чтобы компилятор имел право оптимизировать код на основе знания о том, что предусловия всегда верны. Говорить, что контракты — это аналог assume, это примерно как говорить, что старые throw-описания являются аналогами нового noexcept.
UFO just landed and posted this here
По-моему C++ переусложнили, хоть он и без того был сложный язык. А старые проблемы языка как были, так и остались. Всё закончится тем, что язык вообще никто не будет понимать, разве что сверхлюди, работающие в Гугле или Яндексе.
По идее, его как раз упрощают, вводя новые конструкции. Цель — выделить простое и безопасное подмножество с++ и использовать его более или менее везде. Все остальное — для специальных случаев, должно быть инкапсулировано, а его отсутствие в нормальных местах кода проверяется статическим анализом. См Core C++ Guidelines. Да, выучить с++ от корки до корки становится сложнее, но, положа руку на сердце, приходится признать, что это и так никто не делает. А вот выучить его достаточно, чтобы на нем программировать, становится проще.
Кхм, только сейчас заметил — заголовок неправильный — «С++20» вместо «C++20», из-за этого статья плохо гуглится(
Sign up to leave a comment.