LINUX.ORG.RU

Си с классами

 , ,


0

7

Тупнячка принёс, извиняйте.

Начинаю проект (личный), выбираю на чём писать: C или C++.

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

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

Насколько такой суперсет C / сабсет C++ ака «Си с классами» может быть кошерен?

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

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

Но разница есть.

Конечно есть, языки-то сильно разные.

В Скале эти паттерны выглядят естественно и не так сильно отличаются друг от друга.

Scala сильно моложе C++ и создавалась сразу с поддержкой АлгТД и паттерн-матчинга в языке. Тогда как в C++ это нужно натягивать на уже существующий язык и существующие кодовые базы. Поэтому нужно как-то охватить все существующее многообразие. Т.к. если ввести паттерн-матчинг только для поддержки, скажем, std::pair, std::tuple и std::variant, то это не устроит большое количество разработчиков, которые хотели бы видеть в языке и вот такое:

struct Player { std::string name; int hitpoints; int coins; };

void get_hint(const Player& p) {
  inspect (p) {
    [.hitpoints: 1] => { std::cout << "You're almost destroyed. Give up!\n"; }
    [.hitpoints: 10, .coins: 10] => { std::cout << "I need the hints from you!\n"; }
    [.coins: 10] => { std::cout << "Get more hitpoints!\n"; }
    [.hitpoints: 10] => { std::cout << "Get more ammo!\n"; }
    [.name: n] => {
      if (n != "The Bruce Dickenson") {
        std::cout << "Get more hitpoints and ammo!\n";
      } else {
        std::cout << "More cowbell!\n";
      }
    }
  };
}

Причем здесь, по сути, применяется уже существующий в C++17 синтаксис structured binding. Так что после работы с C++17 это выглядит вполне себе норм.

[.lhs: (*!) l] => { print_leftmost(l); } - что это за херня?

Я так понимаю, что это попытка сделать что-то вроде null safety. Т.е. (*!) знаком указывает, что l всегда должно браться по значению. А вот (*?) говорит о том, что l нужно брать по значению только если l конвертируется в bool и получает значение true. Т.е. если l – это (умный) указатель, то (*?) защитит от матчинга нулевого указателя.

Ну и похоже, что формы (*!) и (*?) есть аналогия с формами extractor pattern (раздел 5.3.2.6):

struct Email {
  std::optional<std::array<std::string_view, 2>>
  try_extract(std::string_view sv) const;
};
inline constexpr Email email;

struct PhoneNumber {
  std::optional<std::array<std::string_view, 3>>
  try_extract(std::string_view sv) const;
};
inline constexpr PhoneNumber phone_number;

inspect (s) {
  (email?) [address, domain] => { std::cout << "got an email"; }
  (phone_number?) ["415", __, __] => { std::cout << "got a San Francisco phone number"; }
  // ˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆˆ extractor pattern
};

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


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

Это всяко принесет больше пользы, чем ругань чужого пропозала на LOR-е.

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

[.lhs: (*!) l] => { print_leftmost(l); } - что это за херня?

Я так понимаю, что это попытка сделать что-то вроде null safety. Т.е. (!) знаком указывает, что l всегда должно браться по значению. А вот (?) говорит о том, что l нужно брать по значению только если l конвертируется в bool и получает значение true. Т.е. если l – это (умный) указатель, то (*?) защитит от матчинга нулевого указателя.

Ну и похоже, что формы (!) и (?) есть аналогия с формами extractor pattern (раздел 5.3.2.6):

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

А самое неприятное что вводя в язык эти новые виды конструкций они обязательно аукнутся новыми «исключениями из правил» потому что весь с++ такой.

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

А вот в C++ все было принципиально не так. И появление полной поддержки C++11 в компиляторах никак не приводило к необходимости переписывать код, разработанный в 2010-ом на C++0x

Блин, ну он и с 2000 года тогда почти не поменялся, что уж там какие какие-то три года между 2010 и 2013.

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

живой труп, мощь Си…

Зато неоднобоко.

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

В разговоре про С++ вы смешиваете понятие UB (данное понятие тупо существует на уровне языка) и алогоритмические ошибки разработчика

Неа, ты выдумал. Разговор был в контексте C-C++-F#, а это уже значительно более широкий контекст.

Далее, вы стенаете, что в 2020-ом настоящая проблема писать многопоточный код и использовать более одного вычислительного ядра. На что вам указывают, что это уже несколько десятков лет вообще не проблема
Речь шла о том, что в реальном мире многопоточные программы на C++ давным-давно утилизируют более одного вычислительного ядра, но вы существуете в какой-то своей вымышленной вселенной. И вам в очередной раз указывают на ваш отрыв от этой самой реальности

Я не намерен доказывать, что я не верблюд, особенно учитывая то, что в треде, судя по всему, кроме нас двоих за беседой особо никто не следит и не напишет ничего в духе «что ты несешь?...».

Я вас прошу определиться с тем, что вы хотите обсуждать: мои проблемы при написании многопоточного кода или же причины появления языка Go в Google

Так у тебя же нет проблем написания многопоточного кода. Это в гугле не умеют писать многопотоки, а у тебя всё получается — что тут обсуждать?

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

В тоже время плюсовый std::variant сам разбирается с тем, что в нем лежит и самостоятельно вызывает деструктор у нужного значения.
А стало это возможным благодаря наличию соответствующих языковых возможностей в C++, коих нет в чистом Си. Что и служит очередным подтверждением того, что C++ более высокоуровневый, чем Си

Разница только в том, что std::variant вызовет деструктор сам, а в Си деструктор придется вызывать руками — описания типов во всем использующем коде будут относительно большие и там, и там. А с атрибутом __cleanup__ автоматическое высвобождение памяти стало возможно и в Си. Так что теперь, Си дорос до уровня C++?

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

А вот как оно будет писаться на Си:

#include <stdio.h>
#include <libactor/actor.h>

#define MSG_STR 100
#define MSG_INT 101

ACTOR_FUNCTION(echo_func, args) {
  while(1) {
    actor_msg_t *msg = actor_receive();
    if (msg->type == MSG_STR)
      printf("%s\n", msg->data);
    else if (msg->type == MSG_INT)
      printf("%d\n", *(int*)msg->data);
    arelease(msg);
  }
}

ACTOR_FUNCTION(main_func, args) {
  actor_id aid = spawn_actor(echo_func, NULL);
  char *msg = "hello world";
  actor_send_msg(aid, MSG_STR, msg, strlen(msg) + 1);
  int val = 24;
  actor_send_msg(aid, MSG_INT, &val, sizeof(int));
}

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

И я бы с удовольствием послушал о том, какие здесь будут проблемы и насколько высоки будут шансы что-то угробить

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

Задно было бы интересно узнать, почему в языке, который настолько сильно выше уровнем C++, вам приходится в одном месте писать actorOf, а в другом actorOf2

В обоих местах можно было бы писать actorOf2. Более того, в обоих местах можно было бы писать actorOf, только

let handleMessage (mailbox: Actor<'a>) msg

поменялось бы на

let handleMessage msg

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

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

Вахтеры просто захотели переплюнуть лисп по скобочкам, а то кресты отставали.

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

Самое неприятное то, что вахтеры не понимают, что основным критерием качества языка является его простота, а не количество фич. Но тут получается парадокс выжившего, потому что все, кто эту простую истину понял, не занимаются «развитием» C++.

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

Как определяется владение msg->data?

Пардон, использовал один и тот же идентификатор в разных местах. «msg» в агенте — это actor_msg_t:

typedef struct actor_message_struct {
  actor_msg_t *next;
  actor_id sender;
  actor_id dest;
  void *data;
  long type;
  size_t size;
} actor_msg_t;

В то же время, «msg» в main_func — это то, чему в агенте соответствует «msg->data». То есть, при пересылке сообщения указанное число байт из «char *msg» копируются в то, что позже будет «void * msg->data», а по «arelease(msg)» эта копия будет высвобождена.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от anonymous

Всего около 10 правил. Как оценишь «качество»

Программа на брейнфаке намного сложнее аналогичной программы на асме.

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

И сразу начал скакать: то язык простой, то программа простая.

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

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

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

Можно хоть с одним

Ваще идеал простоты! Но пусть оценит «эксперт».

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

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

Я писал «критерий качества языка является его простота». Я не писал «критерием качества языка является простота его спецификации», особенно учитывая то, что спецификация пишется на своем языке, который может быть как простым, так и сложным.

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

byko3y ★★★★
()

А что за проект? Может там и Go/Rust нормально заедет. Но если выбирать между C и C++ я бы кресты выбрал. Почему? Чисто субъективно. Не знаю ни того, ни другого (в универе учил только), но на крестах с Qt я как-то пробовал простую программку писать - и мне понравилось. Не аргумент, но всё же. Но вообще C++ адски сложный для меня язык. По крайней мере, те исходники, что я смотрел на Github, я не осилил.

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

Но вообще C++ адски сложный для меня язык. По крайней мере, те исходники, что я смотрел на Github, я не осилил

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

К чему я это пишу? Можно писать просто на крестах. Нет, даже не так, а вот так: НУЖНО писать просто на крестах. То, что ИНДУСтрия продвигает написание сложного кода на крестах — это больше проблема самой ИНДУСтрии. Как грил мне один уважаемый человек «работу нужно делать так, чтобы она никогда не заканчивалась». Особенно если тебе платят за время, а не за выполненное задание.

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

Согласен. Но я вообще немного не про это, а про порог вхождения. Без знания JS разобраться в js-проекте куда проще, чем разобраться без знания C++ в проекте на C++.

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

Но я вообще немного не про это, а про порог вхождения. Без знания JS разобраться в js-проекте куда проще, чем разобраться без знания C++ в проекте на C++

It depends. Вплоть до того, что проект написан почти на чистом Си, с минимальным использованием крестовых фич. Что-то вроде минимальных контейнеров с RAII читается как по маслу. Лямбды теоретически могли бы значительно облегчить чтение кода с итераторами, но хроническая, еще со времен Си, убогость синтаксиса описания функций дала свои плоды.

Но можно написать достаточно простой и бесхитростный код в JS на замыканиях, где функция возвращает функцию, возвращающую функцию... и всё это только для того, чтобы поменять порядок аргументов в callback-е и оставить чистый конечный интерфейс. Особенно весело это отлаживать инструментами разработчика из хрома, которые написаны какими-то отсосными аутсорсными индусами, а потому время от времени отказываются ставить точки останова во вложенных функциях. JS — это довольно бедный по фичам язык, а потому относительно простые функции на нем иногда оказываются удивительно сложны в реализации. Та же беда извела, например, старые диалекты лиспа и scheme, где реализация списков на простейших конструкциях оказывалась ни разу не простейшей, то есть, конструкции простые, но их много — потому такая реализация списков оказалась в выполнении медленной до безобразия.

byko3y ★★★★
()
Последнее исправление: byko3y (всего исправлений: 1)
Ответ на: комментарий от byko3y

Блин, ну он и с 2000 года тогда почти не поменялся, что уж там какие какие-то три года между 2010 и 2013.

Начиная с 2011-го новые стандарты C++ выходят каждые три года. Так что «какие-то три года» – это не много, ни мало, целый новый стандарт.

А ведь непросто сову на глобус натягивать, не так ли? Рвутся.

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

Неа, ты выдумал. Разговор был в контексте C-C++-F#, а это уже значительно более широкий контекст.

Не выдумывал, все ходы записаны. И я с вами веду разговор в контексте C++ vs F#. Другие языки вы за уши притягиваете, потому что с C++ у вас упорно не получается.

Так у тебя же нет проблем написания многопоточного кода. Это в гугле не умеют писать многопотоки, а у тебя всё получается — что тут обсуждать?

Вы просили рассказать как у меня, я рассказал. Если есть вопросы ко мне, то спрашивайте.

Если же вас волнуют проблемы Google, то обсуждайте эти проблемы с теми, кто в курсе проблем Google. Сам я к Google никакого отношения не имею.

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

Так что теперь, Си дорос до уровня C++?

Нет. Разница в том, что std::variant в C++ – это полноценный самодостаточный тип. А union в Си – это полуфабрикат, который невозможно использовать без костылей. Да и с костылями покрываются далеко не все use-cases.

А вот вы разорвали очередную сову в попытках натянуть ее на глобус.

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

А вот как оно будет писаться на Си:

Нет. Так оно не будет писаться.

Внезапно, код даже немного чище и проще, чем твой крестовый.

Не внезапно. Не чище. Не проще.

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

И, во-вторых, можно сходу перечислить ряд претензий в вашему сишному примеру:

  1. Ваш актор не может завершить работу. У него бесконечный цикл внутри.
  2. В вашем примере нет даже диагностики каких-либо ошибок. Возвращаемые значения функций нигде не проверяются.
  3. Освобожение памяти, выделенной под сообщения, осуществляется вручную. Т.е. один преждевременный return/break внутри while и привет memory leak.
  4. Нет никакого контроля за типобезопасностью. Никто и никак не гарантирует, что внутри сообщения лежит null-terminated последовательность символов или int.

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

Не смогу оценить, не зная устройства самой либы.

А как все хорошо начиналось: «Я думаю, что мне не нужно тебе объяснять, насколько сложнее аналогичный код будет описываться в C/C++. И насколько выше шансы угробить систему кривыми руками в C++, и тем более в C.»

Так «насколько выше шансы», а?

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

А вот с этого места поподробнее, пожалуйста, я записываю…

В обоих местах можно было бы писать actorOf2. Более того, в обоих местах можно было бы писать actorOf, только

Во-первых, это не ответ на вопрос.

Во-вторых, F# настолько высокоуровневый, что actorOf не в состоянии разобраться с форматом создаваемого актора.

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

И, во-вторых, можно сходу перечислить ряд претензий в вашему сишному примеру:

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

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

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

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

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

Под твое определение простоты подойдет любое субъективное мнение о простоте, в том числе и моя «простота спецификации языка». Мое определение простоты, по крайней мере, объективно, и не зависит от буйной фантазии субъекта.

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

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

Нет. Меня интересуют возможности языка, благодаря которым можно a) избегать проблем и b) выражать сложные веши (абстракции).

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

Кроме того, именно в C++ не так уж легко провести грань между фичами самого языка (т.е. зашитыми в компилятор) и фичами, реализованными посредством библиотек. Например, туплы в C++ – это чисто библиотечный код. Или записть 100ms – это ведь в большей степени библиотечный код. Или сложение двух экземпляров std::complex – это, опять же, библиотечный код.

а твой оппонент топит с позиции голой задницы самого языка

И приводит в качестве примера код с использованием сторонней библиотеки Akka.NET, которая никоим боком не часть F#.

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

Начиная с 2011-го новые стандарты C++ выходят каждые три года. Так что «какие-то три года» – это не много, ни мало, целый новый стандарт

Ты сравниваешь циклы релиза языка 1983 года с языком с 2010 года в 2010-2015 году. Ты серьезно?

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

Не выдумывал, все ходы записаны. И я с вами веду разговор в контексте C++ vs F#. Другие языки вы за уши притягиваете, потому что с C++ у вас упорно не получается

Мне приходится брать другие языки, чтобы показать, что, твоими стандартами меры удобства языков, C++ сам не дает преимущества над другими языками.

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

Разница в том, что std::variant в C++ – это полноценный самодостаточный тип. А union в Си – это полуфабрикат, который невозможно использовать без костылей

Нет никакой проблемы написать на Си реализацию на макросах, которая даст тип variant__int_str, который можно подставлять в функцию и иметь RAII без необходимости дополнительной варки/жарки.

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

Ты сравниваешь циклы релиза языка 1983 года с языком с 2010 года в 2010-2015 году. Ты серьезно?

Я указываю вам на факты:

  1. auto было добавлено в C++11, который в 2020-ом никак не может считаться «посленими крестами».
  2. auto из C++0x был доступен в C++ компиляторах уже в 2010.
  3. Три года – это релизный цикл нового стандарта языка C++. Так что между 2010-ым и 2013-ем есть принципиальная разница (2010-й – это завершение работы над C++11, 2013-й – это завершение работы над C++14).
  4. Официальный релиз Rust 1.0 – это 2015-й. В 2010-ом Rust был совсем другим языком.

Ну и еще один факт, в свете «языка 1983»: официальный релиз C++ состоялся в 1985-ом году.

Таковы факты.

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

Мне приходится брать другие языки, чтобы показать, что, твоими стандартами меры удобства языков, C++ сам не дает преимущества над другими языками.

Во-первых, у вас не получается показать. Вообще.

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

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

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

Нет никакой проблемы написать на Си реализацию на макросах, которая даст тип variant__int_str, который можно подставлять в функцию и иметь RAII без необходимости дополнительной варки/жарки.

  1. В Сишном union нет информации о том, какое именно значение является актуальным внутри union-а на данный момент. Так что вам придется завести структуру, в которой кроме union-а будет еще и какой-то идентификатор типа значения. Либо вы будете этот идентификатор таскать с экземпляром union-а как-то еще. Что уже делает union несамостоятельным типом.

  2. Вы не сделаете аналоги деструкторов в Си находясь в рамках стандартного Си.

  3. Даже если вы сделаете какую-то структу из union+идентификатор и снабдите ее функцией-деструктором, которую нужно будет использовать через нестандартный атрибут cleanup, то вы никак не гарантируете, что эту функцию будут использовать всегда.

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

Так что нет, разница принципиальная. А вы порвали еще одну сову.

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

C таким же успехом можно поломать С++ код вызывая деструктор вручную где этого делать не надо.

Вообще вся эта мнимая защита за счет сахарка над С в С++ работает точно так же только на уровне соглашения вести себя хорошо и не делать дичь. Так что это заведомо провальная аргументация преимуществ одного над другим.

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

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

Ага, а состояниями между экземплярами одного актора будешь обмениваться дополнительным слоем абстракции? Не говоря уже о том, что в данном случае полиморфизм скрывает готовое полиморфное решение в виде cout.

Ваш актор не может завершить работу. У него бесконечный цикл внутри

Ну это решаем и не такая серьезная проблема, как

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

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

Освобожение памяти, выделенной под сообщения, осуществляется вручную. Т.е. один преждевременный return/break внутри while и привет memory leak

Нынче решается через __cleanup__.

А как все хорошо начиналось: «Я думаю, что мне не нужно тебе объяснять, насколько сложнее аналогичный код будет описываться в C/C++. И насколько выше шансы угробить систему кривыми руками в C++, и тем более в C.»
Так «насколько выше шансы», а?

Я беру и порчу случайный указатель в куче. Твои действия? Как ты запретишь мне это делать? Как ты сможешь продолжить стабильную работу системы дальше? Ты думаешь, что просто так энтерпрайз предпочитает .NET/JVM вместо натива?

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

А вот с этого места поподробнее, пожалуйста, я записываю

Я не буду разбираться в коде твоей либы.

F# настолько высокоуровневый, что actorOf не в состоянии разобраться с форматом создаваемого актора

Запись с явным разделением аргументов функции записывается проще и понимается лучше, чем один полиморфный параметр, в который натыканы все варианты.

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

C таким же успехом можно поломать С++ код вызывая деструктор вручную где этого делать не надо.

Нет.

Если хотите говорить предметно – регистрируйтесь. Чтобы я мог производителей потоков бреда различать.

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

Под твое определение простоты подойдет любое субъективное мнение о простоте, в том числе и моя «простота спецификации языка». Мое определение простоты, по крайней мере, объективно, и не зависит от буйной фантазии субъекта

Вот потому комитетные вахтеры и не могут создать хорошего ЯП. Потому что задача создания простого языка подразумевает оценку субъективной оценки, что есть сложная и творческая задача, которую ни в какие формальности не впишешь. Однако, при успешном проведении этой работы таки 98% людей субъективно скажут «да, это простой и понятный язык».

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

Меня интересуют возможности языка, благодаря которым можно a) избегать проблем и b) выражать сложные веши (абстракции).
В C++ такие возможности есть. В отличии от чистого Си. Поэтому чистый Си меня вообще не интересует, это byko3y почему-то все время кивает в сторону Си

Проблема b решается макросами. Избегать проблем Си не позволяет. Однако, кресты далеко не исчерпывающе позволяют избегать проблем. Полностью избегать проблем повреждения памяти позволяет только виртуальная машина. Потому по твоей же логике F# является более высокоуровневым языком, однако ты упорно продолжаешь применять двойные стандарты.

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

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

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

Ага, а состояниями между экземплярами одного актора будешь обмениваться дополнительным слоем абстракции?

Вернитесь к предмету разговора. Вам был показан шаблонный класс на C++. Вы написали конкретного актора, заточенного на два конкретных типа сообщения на чистом Си. Т.е. вы нифига не повторили исходный код. Откуда взялось какое-то состояние?

И это уже не говоря про то, что нет такой штуки, как «состояние между экземплярами одного актора».

Не говоря уже о том, что в данном случае полиморфизм скрывает готовое полиморфное решение в виде cout.

Это лишний пример того, что есть из коробки в С++ и чего нет в Си.

Ну это решаем и не такая серьезная проблема

Вы сперва проблемы решите, потом количество строк меряйте. И заявления о проще и чище делайте.

О чем я сразу и написал

См. выше по поводу утверждений о короче, проще и чище.

Конкретно я в таких случаях обтыкиваю assert-ами код с ног до головы

Ничего удивительного в том, что у вас потом ничего толком не рабоатет. Только вы из результатов свого рукожопия делаете глубокие выводы по поводу всей ИНДУСтрии.

Я беру и порчу случайный указатель в куче.

Сперва объясните, какое это отношение имеет к многопоточности.

Я не буду разбираться в коде твоей либы.

А как дышал, как дышал.

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

auto было добавлено в C++11, который в 2020-ом никак не может считаться «посленими крестами»

Еще раз: я приводил реальную статистику использования разных версий крестов. Часть проектов до сих пор не перекатилось даже на C++11, не говоря уже про C++17, и тем более очень скромная доля людей в 2020 пользуется C++20. C++17 только в 2020 набирает силу, а в 2018-2019 актуальным был именно C++11.

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

Во-первых, у вас не получается показать. Вообще.

Приехал папа с сыночком к морю. Идут по берегу.
Сынок, мотая головой : "Папа, а где море?".
Папа: "Вот, сынок, видишь - водичка плещется, рыбки плавают, это и есть
море."
Сынок, пуская слюни: "Папа, а где море?".
Папа:"Да вот же, сынуля, парoходик плавет, чайки летают, песочек
желтенький - это и есть море."
Сынок: "Папа, а где море?"
У папы не выдерживают нервы, он берет сына за шиворот и тычет мордой в
морскую воду: "Вот! Вот! Вот море!!!"
Сынок: "Папа-а-а, а что это было?"
byko3y ★★★★
()
Ответ на: комментарий от anonymous

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

Есть принципиальная разница между тем, чтобы «изгаляться и ломать» и тем, чтобы забыть сделать необязательное и никак не контролируемое действие.

сахарочек не спасает увы, даже если это делать не специально.

Да-да. Расскажите мне еще ваших волшебных историй.

Только нет. Бред анонимных надмозгов не интересует.

Реплики от анонимов теперь сразу идут в /dev/null.

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

Еще раз: я приводил реальную статистику использования разных версий крестов.

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

Часть проектов до сих пор не перекатилось даже на C++11,

Это никак не отменяет того постылого факта, что auto появилось в C++11, а не в «последних крестах».

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

В Сишном union нет информации о том, какое именно значение является актуальным внутри union-а на данный момент. Так что вам придется завести структуру, в которой кроме union-а будет еще и какой-то идентификатор типа значения. Либо вы будете этот идентификатор таскать с экземпляром union-а как-то еще. Что уже делает union несамостоятельным типом

Это будет такая же нашлепка на язык, как и std::variant.

Вы не сделаете аналоги деструкторов в Си находясь в рамках стандартного Си

Да. Но! Стандарт крестов какого-то черта включает в себя узкоспециализированные прикладные пакеты, потому аргумент инвалид — «стандарты» несравнимы.

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

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

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

Вообще вся эта мнимая защита за счет сахарка над С в С++ работает точно так же только на уровне соглашения вести себя хорошо и не делать дичь

Он прав в том смысле, что вести себя хорошо и не делать дичь на крестах проще, чем на Си (и сложнее, чем на F#).

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

Это будет такая же нашлепка на язык, как и std::variant.

Ну вот когда эта нашлепка будет частью языка, тогда и можно будет что-то обсуждать. Пока можно лишь повторить то, что union в Си – это полуфабрикат, а не самодостаточный тип, вроде C++ного std::variant.

Стандарт крестов какого-то черта включает в себя узкоспециализированные прикладные пакеты, потому аргумент инвалид — «стандарты» несравнимы.

Это еще что за бред?

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

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

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

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

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

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

Это лишний пример того, что есть из коробки в С++ и чего нет в Си

Я бы не стал этим сильно хвастаться, потому что в итоге UE и Qt заново переписали стандартную библиотеку. То есть, стандартная библиотека — это скорее «библиотека по умолчанию».

Сперва объясните, какое это отношение имеет к многопоточности

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

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