В данной пикче да, но имхо, я бы С++ приравнял к С.
Дело даже не в математике указателей, а в том на сколько у него вырвиглазный синтаксис.
Сравнить хотя бы дженерики в С# и шаблоны в C++ или делегаты с указателями на функции.
Во-первых, С++ к С приравниваете, а потом о шаблонах говорите.
Во-вторых, сравнение дженериков и шаблонов некорректно. Шаблоны позволяют реализовывать куда больше всего, чем дженерики. И одно из важных применений вырвиглазных мозгосломных шаблонов состоит в создании zero-cost (ну или почти zero-cost) штуки, коих много в STL. Если же говорить о простых случаях, без магии, то синтаксис шаблонов не вырвиглазный и практически полностью эквивалентен дженерикам (разве что объявление через template).
В-третьих, сейчас есть std::function и теперь синтаксис "указателя" на функцию в С++ и С# примерно сопоставимы.
Ну и, буду кэпом, разные языки для разных целей. Сравнивать C++ и Python... ну такое. Да, С++ ниебически сложный, местами имеет ниебически упоротый синтаксис, но это все, чтобы поддерживать как можно больше мыслимых парадигм и подходов с минимальным оверхедом. И да, С++ по своему тоже красив. Например, RAII.
Ну так то синтаксис С++ морально устарел и сильно избыточен.
По хорошему выпилить бы из него все устаревшее, отрефакторить существующие конструкции сохранив при этом совместимость с бинарниками и цены бы ему не было бы.
Вся его сложность в легаси. Вот нафига в конструкции if существует возможность присвоения? Да можно сэкономить одну строку, но при этом многие допустят ошибку, в то время, как в C# так нельзя делать.
Что именно в синтаксисе C++ устарело? Моя главная претензия, что комитет очень любит новые фичи, но не любит новые слова, поэтому в С++ просто дохуя знаков с овер9000 вариантами. Первое место, конечно же, у *.
> в то время, как в C# так нельзя делать.
ORLY?
В C#, как и в С++ присваивание является выражением и возвращает значение.
Что же будет, если я по ошибке напишу "="? Для наглядности я напишу "if(a = 3)": Program.cs(10,16): error CS0029: Не удается неявно преобразовать тип "int" в "bool".
Упс, нет никакого особого запрета присваивания, просто C# более строго типизирован и в нем нет неявного преобразования чисел в bool. И это куда серьезнее, чем просто легаси-синтаксис.
К слову, копиляторы C++ тоже отнюдь не глупые. gcc -Wall:
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
И да. Присваивание в условии - это очень удобно в циклах.
Мне кажется, что большая проблема плюсов в том, что для написания верного кода на первых порах нужно либо знать слишком много тонкостей, либо лезть в мануалы/хелп на каждый чих. Все это из-за того, что множество ограничений и особенностей применения либ не описаны в явном виде (так как отсутствуют возможности в языке), зато кодируются каким нибудь костыльным способом типа "struct text_of_my_error;". В результате, при ошибке компиляции какого-нибудь boost::multiindex имеем километровые ошибки, которые невозможно читать. Или отладка какой-нибудь мета-программы - тоже каеф.
Ну и множество вещей, когда все на первый взгляд работает, но работает неэффективно/не совсем так как кажется на первый взгляд.
Так что, мое имхо, для разработки в прод либо нужно иметь уровень выше среднего, либо административно зарезать все эти плюшки на уровне правил в компании.
Думаю, на первых порах как раз легко. Пишешь как на C++03, функции, классы, указатели, STL-контейнеры... Не знаешь и не используешь этот весь пиздец, а налететь на совсем дикую граблю все же надо постараться.
В C# тоже добавили возможность присваивания в if и while выражениях, так что это не такая плохая или устаревшая вещь. Проблема в С++ не в том что такая возможность есть, а в том как эта возможность реализована.
1) По вашей ссылке довольно херня. За C# декларативное (LINQ query syntax) и рефлексия. Функциональщина и там, и там одинаково хуевая (лямбды и Func/std::function). Назвать обобщенное программирование через void* в C более обобщенным, чем темлпейты - надо постараться. Кроме того, как я уже говорил, куда более функциональны, чем дженерики.
2) Все языки так или иначе с легаси, например из-за этого у jvm уебанские дженерики. В С++ из такого вот прям легаси на ум приходят только слишком фривольное неявное приведение и уебанский синтаксис инициализации старых С-структур (точнее, после С++11 это пиздец куча вариантов).
Сложность С++ в том, что он сделан так, чтобы можно было реализовать любое извращение, до которого додумалиь высокоинтеллектуальные задроты из комитета, во всех мыслимых вариантах.
Ну вот пара примеров.
Синтаксис инициализации коллекций в C# и std::initializer_list (и braced-init-lists).
В C# компилятор просто превращает список в последовательность вызовов List.Add() и лист должен реализовывать IEnumerable (метода Add нет в IEnumerable, он сверху должен быть. Это вообще какая-то утиная типизация). Но для парней из комитета С++ это не труЪ вей. Во-первых, STL контейнеры не имеют какой-то иерархии наследования, ведь это виртуальные вызовы, это не круто. Во вторых, что значит, копилятор превращает в набор вызовов Add? Это слишком узко! Мы захерачим так, чтобы любой мог реализовать свои кастмоные классы с возможностью инициализации списком с помощью языковых средств, и теперь у нас 100500 вариантов выстрелить себе в ногу перегрузками.
Лямбды.
В C# лямбды просто захватывают весь контекст по ссылке. В С++ мы имеем стопицот вариантов захвата, по ссылке, по значению, отдельных переменных, всего... [a], [&a], [&], [=], [&, a, &b]...
Что ты имеешь в виду под выразительностью? Вот хаскель, например, очень выразительный язык, и синтаксис простой как палка (большинство вещей - просто синтаксический сахар над базовой функциональностью). Но толку с того?
Оу, привет, детка. Скучаешь? Я, эм... Слышал, ты... программист, да? Кодер? Я тут подумал... здесь есть классная каюта с ноутбуком и wi-fi, где мы могли бы… знаешь... "попрограммировать". Что скажешь? хотя... хотя. Знаешь что? это глупая затея, зря я это предложил. Но... если вдруг передумаешь... ну, знаешь, мало ли... я буду тусоваться рядом с Python'ом, хорошо? Я... пожалуй, пойду.
Если сравнивать синтаксис и выразительность с каким-нибудь C#, то C++ в сухую проигрывает.
Дело даже не в математике указателей, а в том на сколько у него вырвиглазный синтаксис.
Сравнить хотя бы дженерики в С# и шаблоны в C++ или делегаты с указателями на функции.
Во-вторых, сравнение дженериков и шаблонов некорректно. Шаблоны позволяют реализовывать куда больше всего, чем дженерики. И одно из важных применений вырвиглазных мозгосломных шаблонов состоит в создании zero-cost (ну или почти zero-cost) штуки, коих много в STL. Если же говорить о простых случаях, без магии, то синтаксис шаблонов не вырвиглазный и практически полностью эквивалентен дженерикам (разве что объявление через template).
В-третьих, сейчас есть std::function и теперь синтаксис "указателя" на функцию в С++ и С# примерно сопоставимы.
Ну и, буду кэпом, разные языки для разных целей. Сравнивать C++ и Python... ну такое. Да, С++ ниебически сложный, местами имеет ниебически упоротый синтаксис, но это все, чтобы поддерживать как можно больше мыслимых парадигм и подходов с минимальным оверхедом. И да, С++ по своему тоже красив. Например, RAII.
По хорошему выпилить бы из него все устаревшее, отрефакторить существующие конструкции сохранив при этом совместимость с бинарниками и цены бы ему не было бы.
Вся его сложность в легаси. Вот нафига в конструкции if существует возможность присвоения? Да можно сэкономить одну строку, но при этом многие допустят ошибку, в то время, как в C# так нельзя делать.
> в то время, как в C# так нельзя делать.
ORLY?
В C#, как и в С++ присваивание является выражением и возвращает значение.
Что же будет, если я по ошибке напишу "="? Для наглядности я напишу "if(a = 3)":
Program.cs(10,16): error CS0029: Не удается неявно преобразовать тип "int" в "bool".
Упс, нет никакого особого запрета присваивания, просто C# более строго типизирован и в нем нет неявного преобразования чисел в bool. И это куда серьезнее, чем просто легаси-синтаксис.
К слову, копиляторы C++ тоже отнюдь не глупые.
gcc -Wall:
warning: suggest parentheses around assignment used as truth value [-Wparentheses]
И да. Присваивание в условии - это очень удобно в циклах.
После ORLY:
Ну и множество вещей, когда все на первый взгляд работает, но работает неэффективно/не совсем так как кажется на первый взгляд.
Так что, мое имхо, для разработки в прод либо нужно иметь уровень выше среднего, либо административно зарезать все эти плюшки на уровне правил в компании.
А потом, стоит копнуть...
C# поддерживает больше парадигм:
https://ru.wikipedia.org/wiki/Сравнение_языков_программирования#Парадигмы
Не из-за этого он сложный, а из-за требований поддерживать совместимость со старыми версиями.
2) Все языки так или иначе с легаси, например из-за этого у jvm уебанские дженерики. В С++ из такого вот прям легаси на ум приходят только слишком фривольное неявное приведение и уебанский синтаксис инициализации старых С-структур (точнее, после С++11 это пиздец куча вариантов).
Сложность С++ в том, что он сделан так, чтобы можно было реализовать любое извращение, до которого додумалиь высокоинтеллектуальные задроты из комитета, во всех мыслимых вариантах.
Ну вот пара примеров.
Синтаксис инициализации коллекций в C# и std::initializer_list (и braced-init-lists).
В C# компилятор просто превращает список в последовательность вызовов List.Add() и лист должен реализовывать IEnumerable (метода Add нет в IEnumerable, он сверху должен быть. Это вообще какая-то утиная типизация). Но для парней из комитета С++ это не труЪ вей. Во-первых, STL контейнеры не имеют какой-то иерархии наследования, ведь это виртуальные вызовы, это не круто. Во вторых, что значит, копилятор превращает в набор вызовов Add? Это слишком узко! Мы захерачим так, чтобы любой мог реализовать свои кастмоные классы с возможностью инициализации списком с помощью языковых средств, и теперь у нас 100500 вариантов выстрелить себе в ногу перегрузками.
Лямбды.
В C# лямбды просто захватывают весь контекст по ссылке. В С++ мы имеем стопицот вариантов захвата, по ссылке, по значению, отдельных переменных, всего... [a], [&a], [&], [=], [&, a, &b]...