LINUX.ORG.RU

Почему все же с++ такой сложный язык?

 ,


3

4

С++ – сложный язык. Хоть это для каждого по разному и тд, но он очевидно сложнее большинства (всех?) высокоуровневых языков программирования. С другой стороны он очень быстрый и дает тотальный контроль.

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

Ответ на: комментарий от Xintrea

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

thesis ★★★★★
()
Ответ на: комментарий от meliafaro

Вы тоже скоро перестанете, не волнуйтесь. Ещё годков 5 С++ протянет, а дальше только поддержка имеющегося софта.

Как бы я уже настолько старый, что слышу прогнозы о приближающейся вот-вот смерти C++ уже лет 20.

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

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

anonymous
()
Ответ на: комментарий от meliafaro

Последние пару недль пишу на Раст, доволен, как слон.

Вы тоже скоро перестанете, не волнуйтесь. Ещё годков 5 С++ протянет, а дальше только поддержка имеющегося софта.

Типичный сидром эмигранта )). Дальше должно быть больнее, если в цпп ты что-то мог вообще, у тебя сейчас «Фаза эйфории»

Этот период еще называют «медовым месяцем». 
Синдром эмигранта заключается в том, что граждане, покинувшие свою страну пытаются себя убедить в том, что сделали это не зря, что здесь им лучше, а дома было все плохо. 
pavlick ★★
()
Ответ на: комментарий от pavlick

Типичный сидром эмигранта

Прямо дежавю -15 лет форум RSDN темы C# vs C++.

anonymous
()
Ответ на: комментарий от anonymous

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

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

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Конечно-конечно дорогуша, какое еще оправдание ты бы мог родить. Давай пруфы мальчонка.

anonymous
()
Ответ на: комментарий от meliafaro

Ответа не последовало, поэтому я скомпилировал пример сам. Знаешь, что получилось? Знаешь, почему так получилось?

error[E0599]: no method named `emplace_back` found for type parameter `T` in the current scope
 --> main.rs:6:11
  |
6 |         v.emplace_back(xz);
  |           ^^^^^^^^^^^^ method not found in `T`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0599`.

Кстати, этот код даже близко не эквивалентен. Во-первых, элементы xs могут быть разного типа, в том числе может варьироваться lvalue/rvalue, const/nonconst и т.д. Во-вторых, длина xs известна во время компиляции. В третьих, в emplace_back и try_emplace_back передаются аргументы, а не слайс.

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

Ну, не нашёл он такого метода, а что, обязан был?

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

Кстати, о гибкости. Вот только что написал:

match mes_type {
            128..=143 => result = MidiEvent::NoteOn { chan: chanell, note: message[1], vel: message[2] },
            144..=159 => result = MidiEvent::NoteOff { chan: chanell, note: message[1], vel: message[2] },
            160..=175 => result = MidiEvent::PolyAftertouch { chan: chanell, note: message[1], pres: message[2] },
            176..=191 => result = MidiEvent::ControlChange { chan: chanell, num: message[1], val: message[2] },
            192..=207=> result = MidiEvent::ProgramChange { chan: chanell, num: message[1] },
            208..=223 => result = MidiEvent::ChanAftertouch { chan: chanell, pres: message[1]},
            224..=239 => result =  MidiEvent::PitchBend {chan: chanell, lit: message[1], big: message[2]},
            _ => return Option::None
        }; 

Твои плюсы так умеют?

meliafaro ★★★★★
()
Ответ на: комментарий от eao197

в C++… паттерн-матчинг завезут

Как только с++-программа станет не набором из «statement», а из «expression». Только возникнет вопрос: кому нужен еще один недо-ML с перегруженным синтаксисом как у Rust.

anonymous
()
Ответ на: комментарий от meliafaro

А оно и сейчас мало кому надо. Потому что тоже самое запросто можно записать как-то так:

if(range(128,143).in(mes_type))
  result = MidiEvent::NoteOn{chanell, message[1], message[2]};
else if(range(144, 159).in(mes_type))
  result = MidiEvent::NoteOff{chanell, message[1], message[2]};
else if(range(160, 175).in(mes_type))
  result = MidiEvent::PolyAftertouch{chanell, message[1],  message[2]};
else if(range(176,191).in(mes_type))
  result = MidiEvent::ControlChange{chanell, message[1], message[2]};
else if(range(192, 207).in(mes_type))
  result = MidiEvent::ProgramChange{chanell, message[1]};
else if(range(208, 223).in(mes_type))
  result = MidiEvent::ChanAftertouch{chanell, message[1]};
else if(range(224, 239).in(mes_type))
  result = MidiEvent::PitchBend{chanell, message[1], message[2]};
else
  return nullopt;

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

eao197 ★★★★★
()
Ответ на: комментарий от meliafaro

Ну, не нашёл он такого метода, а что, обязан был?

Он обязан был не найти, так как метод явно не задекларирован. Это то, о чем говорит @Lrrr. Полагаю, вопрос об эквивалентности закрыт?

Siborgium ★★★★★
()
Ответ на: комментарий от meliafaro

Давайте я до вас еще раз донесу мысль: подобный код можно было писать и 10, и 15 лет назад, и даже 20. Когда никаких Rust-ов еще и в планах ни у кого не было.

И такого кода было написано просто овердофига.

И, что важно, он все еще продолжает работать.

И, что еще более важно, продолжит работать и когда в C++26 паттерн-матчинг завезут.

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

Для кого-то такие преимущества означают больше, чем лаконичный синтаксис относительно нового языка, который за 6 лет своего существования после релиза версии 1.0 заявил о себе как?

По поводу актуальности ПМ в C++: я уже года четыре говорю, что мне лично ПМ в C++ не хватает. Но понимание среди знакомых C++ников это стало находить разве что год-полтора как. Для многих ПМ в C++ как был, так и остается в категории «а что это и зачем?»

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Да, потому что это позволяет делать вещи, которых иначе сделать было бы нельзя. Это не дичь, просто такова модель крестов. У этого свои плюсы и свои минусы. Для меня плюсы многократно перевешивают минусы.

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

Siborgium ★★★★★
()
Ответ на: комментарий от Siborgium

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

Но по большому счету такие вещи должны делаться на ast макросах, так как гибкость шаблонов С++ тоже не бесконечная. У раста в принципе процедурные макросы есть, но до удобства тех что были в немерле или есть в scala пока сильно не дотягивают.

anonymous
()
Ответ на: комментарий от meliafaro

Это не «гибкость», это сахарок. Посмотрите, вот реализуется простенькое сопоставление с образцом средствами исключительно самого языка. Причем, если уж речь идет про С++20, код (проекта) можно было бы переписать в несколько раз компактнее.

Siborgium ★★★★★
()
Ответ на: комментарий от anonymous

Чувак, вообще-то у него есть нексилый ГитХаб и его зовут спикером на различные выступления. А тебя, думаю, нет.

anonymous
()
Ответ на: комментарий от Siborgium

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

anonymous
()

Добавим разнобразия or каждый кулик хвалит свое болото

Ну что же, наш беспристрастный зритель, на сегодня мы видим что из схватки двух ёкодзун лагерей сторонников С++ и Раста победителем выходит лагерь сторонников D. Как же неожиданно с одной стороны, и не вызывает удивления с другой - если немного подумать. Итак, по порядку:

auto try_emplace_back(auto & v, auto && ... xs) {
    if (some_condition) {
        v.emplace_back(xs...);
    }
}
На D выглядит так:
auto try_emplace_back(T, Args...)(ref T v, auto ref Args xs)
{
    if (some_condition) {
        v.emplace_back(xs);
    }
}
В компилируемом примере мы вызываем `try_emplace_back` с набором аргументов и компилятор нам выводит по ссылке они передаются или нет. В выводе видно, что lvalue компилятор передает по ссылке, rvalue - по значению:
auto try_emplace_back(T, Args...)(ref T v, auto ref Args xs)
{
    static foreach(i; 0..Args.length) // во время компиляции пробегаемся по всем аргументам
        pragma(msg, "xs[", i, "] is reference: ", __traits(isRef, xs[i])); // и выводим как передается этот аргумент - по ссылке или нет
}

З.Ы. pragma(msg) позволяет вывести что-то во время компиляции и очень помогает в метапрограммировании

Далее, вот это:

match mes_type {
            128..=143 => result = MidiEvent::NoteOn { chan: chanell, note: message[1], vel: message[2] },
            144..=159 => result = MidiEvent::NoteOff { chan: chanell, note: message[1], vel: message[2] },
            160..=175 => result = MidiEvent::PolyAftertouch { chan: chanell, note: message[1], pres: message[2] },
            176..=191 => result = MidiEvent::ControlChange { chan: chanell, num: message[1], val: message[2] },
            192..=207=> result = MidiEvent::ProgramChange { chan: chanell, num: message[1] },
            208..=223 => result = MidiEvent::ChanAftertouch { chan: chanell, pres: message[1]},
            224..=239 => result =  MidiEvent::PitchBend {chan: chanell, lit: message[1], big: message[2]},
            _ => return Option::None
        }; 
в D выглядит так:
    switch(i)
    {
        case 128: .. case 143: result = MidiEvent.NoteOn (chanell, message[1], message[2]); break;
        case 144: .. case 159: result = MidiEvent.NoteOff (chanell, message[1], message[2]); break;
        case 160: .. case 175: result = MidiEvent.PolyAftertouch (chanell, message[1], message[2]); break;
        case 176: .. case 191: result = MidiEvent.ControlChange (chanell, message[1], message[2]); break;
        case 192: .. case 207: result = MidiEvent.ProgramChange (chanell, message[1]); break;
        case 208: .. case 223: result = MidiEvent.ChanAftertouch (chanell, message[1]); break;
        case 224: .. case 239: result = MidiEvent.PitchBend (chanell, message[1], message[2]); break;
        default: return Result(None());
    }
Компилируемый пример (с некоторыми несущественными упрощениями)здесь

В общем, хотя в D пока нет именованных аргументов, есть case и break, тем не менее получается что у D результаты получше будут - на нем можно написать оба примера, на С++ тоже, кстати, можно написать оба. А вот Раст хорош только во втором случае.

yetanother ★★
()
Ответ на: комментарий от Siborgium

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

Из-за этого «средствами исключительно самого языка» C++ фактически 13 лет совсем не развивался. Ладно бы в нем как в немерле были синтаксические макросы, тогда да было бы реально такое сделать, но шаблоны для этого просто непригодны. Ладно хоть комитет одумался и начиная с C++11 пусть и со скрипом все-таки расширяют язык.

anonymous
()
Ответ на: комментарий от anonymous

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

Ну формально можно к этому придраться. Но на практике это отлично работает. Даже если это формально и является компрометацией абстракции, это все равно отлично работает. Если не вытаскивать эту функцию в публичный API то вообще ничего не надо делать. А если вытаскивать, то документация нужна в любом случае. Можно еще навернуть кода, чтобы он формировал внятные ошибки для пользователя, но тут у плюсов бедновато со средствами и придется помучится в стиле boost или eigen.

yetanother ★★
()
Ответ на: комментарий от anonymous

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

yetanother ★★
()
Ответ на: комментарий от yetanother

Макросы безусловно очень мощный инструмент и в этом их беда - есть жалобы что это приводит к «балканизации» языка

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

anonymous
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от anonymous

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

Я не то чтобы защищаю eao197, скорее нападаю на тебя - может это ты нам покажешь что-то, чтобы мы со стороны посмотрели и нам стало ясно кто есть кто?

yetanother ★★
()
Ответ на: комментарий от anonymous

немерле и ним в этом плане конечно сильны. Я бы тоже хотел, чтобы в D были ast macros, но вот автор языка Уолтер Брайт считает, что это повредит языку из-за этой самой «балканизации». Сам я анализа не делал насчет «балканизации» - за что купил, за то продал. Он подтверждает, что ast макросы это очень сильный инструмент, но не дает его нам, печаль.

yetanother ★★
()
Ответ на: комментарий от anonymous

Я не его защитник. Я с тобой согласен в плане что он агрессивный (ну по крайней был таковым в тех тредах, которые я читал, а это было давно). Просто говорю что надо бы стараться на вещи объективно смотреть.

anonymous
()
Ответ на: комментарий от yetanother

Вот да, мне близка позиция этого чувака.

anonymous
()
Ответ на: комментарий от anonymous

Причем не просто агрессивным был, а агрессивным и инфантильным фанатиком.

Но повторюсь, это было года 2 назад, а люди меняются. Иногда и в лучшую сторону. Этот тред я не читал.

anonymous
()
Ответ на: комментарий от Xintrea

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

Что это значит и как должно быть?

DarkEld3r ★★★★★
()
Ответ на: комментарий от Siborgium

В С++ вызов деструкторов хотя бы гарантируется.

Разве есть какие-то различия с растом? В С++ (тоже) есть std::quick_exit и прочее.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Lrrr

А теперь представь, к чему приводит эта «фича», если у нас есть большое дерево вызова функций

К явному интерфейсу и как следствие к более читабельному коду?

DarkEld3r ★★★★★
()
Ответ на: комментарий от yetanother

немерле и ним в этом плане конечно сильны.

Еще scalа есть с такими же макросами. Вроде она нисколько ни балканизировалась. Думаю чем мощнее базовый язык, тем меньше шансов на такое расползание.

anonymous
()
Ответ на: комментарий от yetanother

Можно еще навернуть кода, чтобы он формировал внятные ошибки для пользователя, но тут у плюсов бедновато со средствами и придется помучится в стиле boost или eigen

Так концепты же, и сообщение об ошибке будет ясным, а не десятиэтажным, и копать ничего не надо.

pavlick ★★
()
Ответ на: комментарий от meliafaro

Кстати, о гибкости.

с такими критериями x86-64 ассемблер самый гибкий например(1978 год)

daa
твой раст так умеет?

anonymous
()
Ответ на: комментарий от pavlick

Так концепты же

Ну я просто по независящим от меня причинами сижу еще на с++11, поэтому вспомнил про них, когда уже запостил. А так да, это как раз их задача.

yetanother ★★
()
Ответ на: комментарий от DarkEld3r

да-да, конечно, к более читабельному.

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

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

Реальное решение проблемы есть только одно, и оно уже реализовано в C++: описывать не то что мы разрешаем делать с типом, а то что запрещаем. Тогда нам придётся изменить ровно одну сигнатуру. Да, тут есть свои недостатки (например, кроме сигнатуры приходится смотреть еще и в тело функции), но главного достоинства они не перевешивают.

Lrrr ★★★★★
()
Ответ на: комментарий от unC0Rr

Реально, функция, проверяющая, что значение находится в интервале, называется in, а не contains?

Для меня английский сильно не родной, так что вы, должно быть правы: contains или какой-нибудь holds правильнее, чем in.

Но принципиально подход не изменится.

eao197 ★★★★★
()

Что мне не нравилось в С++ еще с 90х - это отсутствие динамических многомерных массивов. Моделирование их на основе одномерного - так себе идея. Нет перегрузки оператора [] с несколькими параметрами. Обилие разных стандартов тоже напрягать стало. И шаблоны…сами по себе, пока ты сам для себя ваяешь - это еще ничего, как хочешь извращайся. А вот, когда код большой и пишется группой товарищей, то беда. Такое каждый наворотит. Отлаживать потом чужие шаблоны с километровыми распечатками, что там не так - еще та радость. Знавал таких монстров, творящих такие шаблоны, что компиляторы падали с внутренней ошибкой.) Таких сразу надо из рогатки расстреливать, во избежание)))

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.