Особенно рекомендуется тем, кто не знает, чем С++ отличается от С. Вернее, знает по тому что пишут в учебниках - про то, что в С++ есть классы и инкапсуляция, а в С нет, ну короче вот это всё враньё.
Те, кто, например, знает, что сугубо классовый и инкапсулированный Direct3D можно свободно использовать в С, узнают/вспомнят из статьи, чем опасно использование С++ в реалтайм-программах типа игровых движков.
Ну а Jackhammer, в котором некоторые диалоги открываются по полсекунды, отлично иллюстрирует, во что это в итоге выливается. И если редактору это ещё можно простить, то движку - уже нет.
А я, в свою очередь, который уже год при разработке Volatile балансирую на острие ножа - с одной стороны, пытаясь совмещать фичи С++, упрощающие написание, compile-time проверку, понимание и поддержку кода, с простотой, производительностью и низкоуровневым доступом (там где он нужен) языка С. Но, конечно, мало кто это в итоге оценит - народу куда важнее красочные шейдеры.
Лучше работать на старом движке, чем на новом. Ту же самую дилемму приперли сюда, что лучше, кто хуже. Оба хуже - это однозначно. Лучших никогда не бывает. Приходится искать компромисс, между тем или иным, а не сравнивать как тупой блогекомментартор из yt или vk или fb.
Однако большинство людей под С++ понимают так называемый «современный C++», со счетчиками ссылок, классами, исключениями, шаблонами, лямбдами, STL, Boost, и так далее. То есть, тот C++, на котором вы пишите, почти как на Java, в котором никогда не встречаются обычные указатели, и вот это все. Если вам очень важна скорость, то писать на таком C++ вы не сможете. Если же он вам подходит, то лучше взять Java, Go или любой другой высокоуровневый язык по вкусу.
Т.е. тем, кто хочет писать код с шаблонами и исключениями, автор предлагает использовать язык, в котором нет ни того, ни другого? (это про Go)
В зависимости от задачи, может пригодиться разное подмножество C++, нужно просто уметь выбирать и не тащить всё подряд. Я думаю, для задач алгоритмических, C++ с шаблонами подходит (но без ООП головного мозга). В самом деле, не реализовывать же для каждого типа quicksort, ассоциативные и динамические массивы. Мне, признаться, не особо понравилось этим заниматься, когда я писал курсовую, где требованием было писать на Си, ибо по сути пришлось дублировать код.
В комментах к статье вот упомянули Eigen, который может посоревноваться с blas засчёт того, что работает с матрицами на уровне целых выражений.
RAII очень уместен тогда, когда время жизни ресурса заранее известно. Нет никакого удовольствия в goto Error; или дублировании кода очистки во всех точках выхода. Умный указатель на каждый чих - конечно плохая практика, но такой стиль и не является рекомендуемым. Тут я бы хотел упомянуть про такую фичу языка D как scope(exit), которая позволяет писать вот такой код:
Никаких оберток, ни конструкторов, ни деструкторов. В Си есть подобная штука, но только как расширение компиляторов.
Если бы в Си были шаблоны и подобный RAII (но закрепленный в стандарте), то надобность в C++ может быть и вовсе отпала. Что до ООП, то его при надобности можно и на Си писать.
Остаются ещё исключения - штука настолько спорная, что даже в стандартной библиотеке C++ так и не решили, нужно их кидать или нет, из чего родилась функция std::ios::exceptions. Для меня большим минусом исключений является то, что они не являются частью объявления функции. Соответственно, не знаешь чего ожидать. А когда в дело вступают наследование и шаблоны, всё становится ещё мутнее.
FreeSlave писал: Т.е. тем, кто хочет писать код с шаблонами и исключениями, автор предлагает использовать язык, в котором нет ни того, ни другого?
Он предлагает Java.
Java - как Греция, там всё есть.
Цитата:
FreeSlave писал: В самом деле, не реализовывать же для каждого типа quicksort, ассоциативные и динамические массивы.
В смысле? Зачем ассоциативные массивы для quicksort?
Цитата:
FreeSlave писал:
RAII очень уместен тогда, когда время жизни ресурса заранее известно.
В си можно реализовать RAII и без gcc-шных расширений. Через динамический массив структур, хранящих адреса и деструкторы, с соответствующими вызовами-обёртками. Иплементацию в последнем случае можно скрыть, чтобы не мозолила глаза. Но выглядеть после С++ будет, разумеется, довольно дико и непривычно.
Цитата:
FreeSlave писал: Остаются ещё исключения - штука настолько спорная
Есть же raise/signal? Или важен именно факт передачи доп. информации в виде объекта исключения?
XaeroX писал: В смысле? Зачем ассоциативные массивы для quicksort?
Не знаю. Я о таком и не писал.
XaeroX, о каком raise речь? А если под signals имеются в виду POSIX-сигналы, то у них же и назначение иное.
Я наверно не совсем внятно выразился. Я не считаю, что наличие исключений, обязательно для "улучшенного" Си. Наоборот, выразил свою неуверенность в этом вопросе.
FreeSlave писал: В самом деле, не реализовывать же для каждого типа quicksort, ассоциативные и динамические массивы.
Извини, видимо, не заметил запятую и прочитал совсем другое по смыслу.
Но я не вижу проблемы делать шаблоны на С - с использованием "магического" типа void*. Та же qsort так реализована и работает с любыми типами (при условии последовательности и непрерывности области памяти). Имхо, единственное достоинство шаблонов С++ - это compile-time проверки.
Цитата:
FreeSlave писал: А если под signals имеются в виду POSIX-сигналы, то у них же и назначение иное.
Ну там можно и свои.
Ещё есть вариант с setjmp/longjmp.
Ну MS-specific __try/__except/__finally.
XaeroX писал: Но я не вижу проблемы делать шаблоны на С - с использованием "магического" типа void*. Та же qsort так реализована и работает с любыми типами
Да, есть такое. И так реализованы многие алгоритмы в сторонних библиотеках. Но это подразумевает лишние разыменования, как указателя на функцию, так и данных по указателю на void. В контексте производительности это не очень хорошо. Шаблоны позволяют сгенерировать нужный код без таких жертв.
FreeSlave писал: Но это подразумевает лишние разыменования, как указателя на функцию, так и данных по указателю на void. В контексте производительности это не очень хорошо.
Зато это удобно в случае, если есть арифметика указателей - например, выполнение однотипных операций с массивом. Указатель уже есть. В цикле в любом случае были бы разыменования.
За попытки переложить менеджмент памяти на сторонние библиотеки, умные указатели и встроенные средства языка погромисту надо отрубать руки. Память надо уметь выделять самому. Хапнул большой кусок и вручную там разместил всё нужное. А потом удалил за один вызов. Вот как надо.
Тогда фргаментация стремится к нулю.