Pull to refresh

Comments 53

Хорошо, наконец-то до этого додумались. Думаю, с помощью #feature можно будет постепенно отключать части языка, являющиеся ошибками языкового дизайна и подключать исправленные реализации. Шон Бакстер это разработчик Circle - мощного расширения С++, в котором как раз все это реализовано.

Шон и его фанаты как раз таки поливают профили говном при каждой возможности. В Circle он добавил боров чекер с лайвтаймами и unsafe из Раста, который они продвигают в виде "Safe C++" вместо профилей.

И правильно делают, потому что профили в том виде, в котором их продвигают, не работают и принципиально работать не могут.

Профили, это не конкретная реализация безопасного С++, а только предложение с помощью которого это можно повысить безопасность разработки на С++ без нарушения обратной совместимости. Что поливается говном, если никакой реализации профилей безопасности пока не существует?

Что поливается говном, если никакой реализации профилей безопасности пока не существует?

Идея, что код на C++ можно корректно автоматически анализировать по функции за раз, не требуя при этом аннотаций от программиста. В исходном коде на C++ попросту недостаточно для этого информации.

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

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

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

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

Чувствуете разницу? В первом случае предлагается выкинуть наработки нескольких десятилетий и переписать все на новом языке, тогда как использование аннотаций (читай профили безопасности) позволяют повышать безопасность кода на С++ без выкидывания уже работающего кода.

Имхо, нужен простой язык по аналоги Си с минимум синтаксиса и всяких фич со встроенной безопасностью. Что новые варианты C++, что Rust это адски переусложненные решения которые мешаю фокусироваться на написании прикладного кода. Все становится ещё хуже когда нужо читать код очередного гения который решил, что в его коде обязательно нужно использовать все имеющиеся в языке фичи, разбить код, умещающийся в один фал, на 10 папок и 10 факлой в каждом с одной функцией. Благодаря чему примитивное решение которое на Си можно осились за пару часов превращается в библиотеку по которой можно писать отдельну диссертацию, то ли по психологии толи по литературе с целью обьяснить - что хотел сказать автор.
Языки с возможностями создания пользовательских типов и всякими специфическими фичами, к сожалению поощряют такой стиль написания кода.

Хм... Есть Zig, мне он нравится, но порой не хватает алгебраических типов и трейтов.

С другой стороны, Лисп мне нравится в чём-то больше, чем Zig.

Скажите, а что вы имеете в виду под пользовательскими типами?

Структуры - это уже типы.

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

раст активный язык как и С++, С использует пассивные блоки памяти по дефолту в структурах, наверно это

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

грубо говоря кирпичики С пока выглядывают из С++, но он уже не С давно

Скажите, а что вы имеете в виду под пользовательскими типами?

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

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

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

Я пишу на Zig и мне очень не хватает трейтов.
Думаю, что тут кому как нравится.

Что новые варианты C++, что Rust это адски переусложненные решения которые мешаю фокусироваться на написании прикладного кода. 

Фичи - это только инструменты. Все зависит от того, как вы их применяете, и насколько они уместны для конкретного применения. Можно дрелью быстро и надежно делать отверстия, а можно гвозди пытаться забивать и удивляться, что фигня какая-то получается.

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

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

…игре в увлекательную викторину «а не UB ли я сейчас делаю?»

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

скорее наоборот, в современном C++ (в т.ч. Core Guidelines, про которые в статье говорится), довольно много сделано чтобы уменьшить количество неоднозначных и опасных мест, в сравнении со старыми стандартами и чистым С.

Это распространенное заблуждение. С++ унаследовал почти все UB из С, и добавил гораздо больше новых.
Например при работе со string_view легко получить UB, как и в С с нуль-терминированными строками.
Ну а move-семантика отстреливает ноги на каждом шагу. Такое чувство что в C получить use-after-free даже сложнее.

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

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

они там явно рекомендуют не использовать некоторые опасные и сомнительные конструкции

Ключевое слово тут "некоторые", причем очень небольшой список. То, что я выше описал, Core Guildelines никак не исправляет.

Как и проблемы, пришедшие из С. Например, вы знаете, что такое Integer Promotion?

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

Но с другой стороны, UB в коде на С гораздо легче заметить глазами. Да и статическим анализаторам намного проще: гораздо меньше ложно-положительных и ложно-отрицательных случаев.

А вы сможете утверждать, что знаете все несколько сотен UB в С++? Вот в С их вполне реально выучить все.

Я тут недавно узнал (и до сих пор обескуражен этим фактом), что простая C++20-фича (достаточно новый стандарт?) опасна:

template<auto V>
const auto& make_static()
{
  return V;
}

Сможете сходу сказать, когда и чем?

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

если шаблон убрать то ничего не поменяется

Если шаблон убрать, то откуда взять V?

включая UB, который в данном случае практически гарантирован

Нет, эта функция иногда вполне корректна. А иногда — нет. Почему?

ну очевидно что вместо V мы подставляем свое что надо если это тип

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

Я бы хотел посмотреть на ваш "иногда корректна" сценарий, потому что для меня это или говнокод с UB или без UB.

проблема в том, что в подавляющем большинстве случаев это будет возврат указателя на объект стека

V не обязан быть на стеке. В какой момент на стеке оказывается шаблонный аргумент здесь?

template<int V>
auto foo() { ... }

foo<42>();

Я бы хотел посмотреть на ваш "иногда корректна" сценарий, потому что для меня это или говнокод с UB или без UB.

Я не помню точную формулировку в стандарте, но это UB с типами вроде intов и не UB с class non-type template parameters'ами (что и является C++20-фичей, и что вообще оправдывает существование этой функции — лично мне такое было нужно ровно для class NTTP).

Например, этот код компилируется (что означает, что там нет UB), а если раскомментировать, то нет:

template<auto V>
constexpr const auto& make_static()
{
  return V;
}

struct S
{
    int val;
};

constexpr int foo()
{
    constexpr auto& v1 = make_static<S { 42 }>();
    //constexpr auto& v2 = make_static<42>();
    return v1.val;
}

static_assert(foo() >= 0);

код на плюсах занимал в несколько раз меньше строк и был гораздо понятнее для чтения чем аналогичный код на чистых сях

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

В том и дело что в всего лишь несколько строк

Вы кажется не понимаете разницу между "в несколько строк" и "в несколько раз меньше строк"

это ваш собственный код

Вообще не угадали

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

Опять не угадали, другие разработчики в команде тоже согласились, что стало гораздо проще :)

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

Гуру (которые выдумывают) и программисты - совершенно разные люди. Независимо от ЯП; С++ или любой другой.

Пока программисты на С++11 и С спокойно пишут реальные операционки, драйвера и прочие реальные программы, гуру других языков спорят какой питон правильнее 2 или 3 или спорят о том какой из 100500 фронтэнд и бэкэнд фреймворков лучше, а пока спорят выходят еще 100 фреймворков.

Утверждение примерно того же порядка.

Бьёрн Страуструп

Он, кстати, Бьярне Строуструп (там даже есть .wav-файл с правильным произношением):
https://www.stroustrup.com/bs_faq.html#pronounce

P.S. My first name is Bjarne - not Bjorn (not a name), Bjørn (a related but different name), nor Barney (an unrelated name). My second name is Stroustrup - not Stroustroup, Stroustrop, Strustrup, Strustrop, Strustroup, Straustrup, nor Straustroup (documents using each of these misspellings can be found using google).

Эти профили были представлены еще в 2023 году, и их основная идея, не придумывать новый язык или расширять синтаксис С++, а при необходимость применять к коду (фрагментам кода) те или иные дополнительные ограничения (проверки) не меняя сам язык.

The result of a profile is ISO standard C++ code; there are no changes in semantics, though typically the meaning of UB must be restricted (as is allowed by the definition of UB).
If no profile is requested, ISO C++ – warts and all – is available unchanged.

А в конце 2024 года уже Herb Sutter представил конкретную семантику профилей (документ не доступен без слова из трех букв).

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

Я правильно понял, что засовывают ежа в ужа планируется реализовать в С++ то, что нативно реализовано в Rust и некоторых других более молодых языках?

PS. Я не имею ничего против С++, а говорю про то, что вряд ли удастсято идеально реализовать в таком ставшем давно классическим "возрастном" языке, как С++, ничего при этом не сломав в нём.

вряд ли удастсято идеально реализовать в таком ставшем давно классическим "возрастном" языке, как С++, ничего при этом не сломав в нём.

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

  • никаких нарушений диапазонов или nullptr

Ну вот не понимаю я эту повсеместную борьбу с nullptr

Одна из самых редких ошибок в коде и в целом раздутая до невероятных масштабов проблема.

забавно...

на текущий момент у статьи 3.5K просмотров. и раз каждый второй здесь Эксперт С++, то хотя бы 1 из 100 просмотрели оригинал https://cacm.acm.org/blogcacm/21st-century-c/ . значит 70 глаз как минимум!

кто-то нашел ошибки у Страуструпа? ха! да ни один ;)

ну, например:

import std;                               
using namespace std;         // make all of the standard library available
vector<string> collect_lines(istream& is) // collect unique lines from input
{

          unordered_set s;               // hash table
          for (string line; getline(is,line); )
               s.insert(line);
          return vector{from_range, s};  // copy set elements into a vector

}

unordered_set s; - это блин что такое? опять на весь Мир рукожопие??

Там ещё вёрстка кода поехала. На его сайте статья висит исправленная (unordered_set<string>) и дополненная (I wanted Lines read as lines) и всё равно с ошибками (в скобках:{...)).

https://stroustrup.com/21st-Century-C++.pdf

Хм, на godbolt.org нет ни одного компилятора, который бы запустил код. У msvc есть поддержка нужной фичи (__cpp_lib_containers_ranges), но в тамошней версии нет поддержки модулей и ещё from_range-конструктор unordered_set'а не берёт istream_iterator в качестве аргумента (старый компилятор или ошибка у Страуструпа - не знаю).

unordered_set s;

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

не вижу какого-то особо повода для криков и восклицаний.

Вряд ли. Там шаблонные скобки не возвращали вручную, их штук 50 в статье. Их не хватает только в unordered_set и в 2 случаях из 3 их можно опустить, полагаясь на вывод типов.

Я правильно понимаю, что с профилями должны будут заморачиваться те, кто понимает, как надо? А те, кто говнокодил, будут продолжать спокойно это делать? Если так, то будет очередное мертворожденное. Пора прекращать летать в облаках. Единственной путь в этом направлении - ставить жёсткие ограничения по умолчанию, а не наоборот

Sign up to leave a comment.

Other news