Re[5]: Microsoft исключит C++ к 2030 году...
От: dsorokin Россия  
Дата: 24.12.25 19:31
Оценка:
Здравствуйте, Shmj, Вы писали:

S>В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.


Конкретно этот кусок кода можно было бы сделать или через ADT, или просто через одну структуру с навешенными туда лямбдами

Однако важнее другое. ООП — это, прежде всего, объекты с изменяемым состоянием (у тебя в примере это не выражено). Например, это полезно для десктопного GUI. Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности... Да и эти жесткие правила по ссылкам, в тысячу раз более удобная семантика перемещения по сравнению с твоим C++ — все это хорошо заточено именно под многопоточку, под асинхронность (народ реально путается в семантике перемещения, когда пишет на C++, а потому предпочитает обходить ее стороной, а вот на Rust эта семантика также естественна как воздух). В общем, приоритеты такие, где ООП создало бы больше проблем, чем принесло пользы (из-за мутабельности, которой у тебя в примере нет)

А так. Я сам люблю баловаться десктопным программированием с GUI. Мне вот для таких задач ООП видится крайне полезным (особенно с линеаризацией наследования как в Common Lisp или Scala). Я совсем не против ООП, но вот в тех задачах, под которые заточен конкретно Rust — там ООП, скорее, мешает

И тут на самом деле, Rust далеко не единственный язык, где отказались от ООП из-за многопоточности и конкурентности. Пример другого языка — clojure

В одном учебнике по математическому программированию было написано, что не существует универсальных методов оптимизации, которые были бы хороши для всего. Готов перефразировать это и сказать, что точно также не существует универсальных языков программирования, которые были бы хороши для всего сразу. Я вот сейчас для себя освежаю знания по языку Scheme. До чего же красивый и выразительный язык! Но только Scheme (так же как С++, Rust, Java, C#) не является универсальным языком программирования (про термин "общецелевой язык программирования" все уже давно забыли — в 2026 году этот старый термин выглядит как выцветший кусок ткани). На Scheme было бы интересно написать какую-нибудь сложную логику и встроить в программу на С++ или на Java, но использовать для высоконагруженного сервера я бы не стал, ограничившись Java или даже С++ c Rust

То есть, твое желание видеть везде ООП похвально, но не всегда целесообразно, потому что ООП тоже не универсально!

Что касается исходной темы. Мне сдается, что с такими популяризаторами технологии и никаких конкурентов не надо!
Re[6]: Microsoft исключит C++ к 2030 году...
От: Shmj Ниоткуда  
Дата: 24.12.25 20:05
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности...


То есть браузеры, графические движки — лучше на нем не писать? Там лучше C++?

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

А то что сейчас — это параша, смотрите мой пример. Вроде какой-то макрос был, чтобы не писать по сто раз всех наследников — но это полумеры. К полумерам не привык.

D>А так. Я сам люблю баловаться десктопным программированием с GUI. Мне вот для таких задач ООП видится крайне полезным (особенно с линеаризацией наследования как в Common Lisp или Scala). Я совсем не против ООП, но вот в тех задачах, под которые заточен конкретно Rust — там ООП, скорее, мешает


Но так его же хотят тащить и в браузеры и во все другое.

D>То есть, твое желание видеть везде ООП похвально, но не всегда целесообразно, потому что ООП тоже не универсально!


Так если в языке есть возможность ООП — вас никто не обязывает эту возможность использовать
=сначала спроси у GPT=
Re[2]: Microsoft исключит C++ к 2030 году...
От: Артём Австралия жж
Дата: 24.12.25 21:42
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Слабоумие и отвага...


Там никто не знает, что этот код делает. Когда коду 30 лет. Чувак предложил попытаться победить копролит с помощью модного ныне LLM — это чисто политическое решение. Ибо если счас не изображаешь ярого фаната "Эй Ай", сильно рискуешь быть помеченным как "луддит" и сокращённым, чтоб освободить место "Эй Ай" специалистам.

Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".
Re[7]: Microsoft исключит C++ к 2030 году...
От: dsorokin Россия  
Дата: 25.12.25 05:11
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Здравствуйте, dsorokin, Вы писали:


D>>Только Rust нацелен на многопоточные серверы (как особенно стало ясно после добавления async/await). А вот с многопоточкой ООП, знаешь, не очень-то и дружит из-за мутабельности...


S>То есть браузеры, графические движки — лучше на нем не писать? Там лучше C++?


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


S>А то что сейчас — это параша, смотрите мой пример. Вроде какой-то макрос был, чтобы не писать по сто раз всех наследников — но это полумеры. К полумерам не привык.


Так. Погоди! Давай разберем. Развесистую иерархию с глубоким наследованием я видел только в тулкитах GUI. Может быть, что это встречается где-то еще, но лично я не встречал больше нигде, хотя легаси-кода видел много разного, с которым приходилось работать. Причем, развесистая иерархия контролов GUI — это тоже вопрос еще, а насколько это все хорошо, потому что малейшее изменение в предках может привести к непредсказуемым изменениям в наследниках, ибо наследование реализации порождает сильную связность. А сильная связность — вещь не очень хорошая в плане перспективы поддержки

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

Так вот, подходим к главному моменту. Наследование интерфейсов есть в Rust! Как есть в Haskell, откуда они ее и взяли по сути — наследование характеристик, трейтов, они же классы типов. Трейт — это по сути и есть что-то вроде интерфейса, который могут поддерживать сразу одновременно разные типы данных.

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

Оставим теоретизирование. Теперь просто скажем, что ты несколько преувеличиваешь в своих выводах. Браузеры и графические движки можно писать и на Haskell, но лучше на языке без сборки мусора. Поэтому Rust тоже подходит, как и C++. И я не против C++ как такового. Я денежку зарабатываю на C++, но я против его сложности. Меня все возрастающая сложность C++ пугает и настораживает. И эта сложность выглядит как каток, который все сметает на своем пути, и который не остановить

Надеюсь, что я некоторые ключевые моменты довольно подробно описал
Re[8]: Microsoft исключит C++ к 2030 году...
От: Shmj Ниоткуда  
Дата: 25.12.25 06:05
Оценка:
Здравствуйте, dsorokin, Вы писали:

D>А наследование реализации, как мы выяснили выше, это несколько сомнительная вещь. Кажется, что вот мы выиграем с нею, выиграем в краткосрочном плане, а в долгосрочном плане наследование реализации может только усложнить поддержку кода, усложнить тестирование


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

https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/core/html/forms/email_input_type.h

EmailInputType -> BaseTextInputType -> TextFieldInputType -> InputType -> GarbageCollected<InputType>

Как видите — в самом современном браузере — лучше не бывает — используется многоуровневое (5 уровней) наследование. И что с этим делать? Представьте каким мусором это будет на Rust.

Или же нужно делать Rust++, как уже ранее MS делали J++ (емнип).
=сначала спроси у GPT=
Re[3]: Microsoft исключит C++ к 2030 году...
От: Pzz Россия https://github.com/alexpevzner
Дата: 25.12.25 06:15
Оценка:
Здравствуйте, Артём, Вы писали:

Pzz>>Слабоумие и отвага...


Аё>Там никто не знает, что этот код делает. Когда коду 30 лет. Чувак предложил попытаться победить копролит с помощью модного ныне LLM — это чисто политическое решение. Ибо если счас не изображаешь ярого фаната "Эй Ай", сильно рискуешь быть помеченным как "луддит" и сокращённым, чтоб освободить место "Эй Ай" специалистам.


Ну так взял бы что-нибудь безопасное. Типа, рефакторинг говнокода с помощью ИИ. А не "взять — переписать". Ясно же, что не перепишет. А при этом взялся.

Аё>Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".


Как их отличить-то, коммиты с ИИ от коммитов, написанных руками?
Re[8]: Microsoft исключит C++ к 2030 году...
От: ononim  
Дата: 25.12.25 09:13
Оценка:
D>Так. Погоди! Давай разберем. Развесистую иерархию с глубоким наследованием я видел только в тулкитах GUI. Может быть, что это встречается где-то еще

15 лет назад (а более свежие проекты не хотелось бы светить) я реализовывал под винду application paravirtualization, в нем к примеру был класс узел реестра, класс узел файловой системы у которого еще был поднаследник файл, а оба они были наследованы от базового класса узел, который реализовывал базовые вещи для работы с путями, виртуальными хэндлами с подсчетом ссылок и прочее, наследники расширяли и отчасти модифицировали это все дело своим функционалом.
Как много веселых ребят, и все делают велосипед...
Re[2]: Microsoft исключит C++ к 2030 году...
От: Sharov Россия  
Дата: 25.12.25 09:55
Оценка: :)
Здравствуйте, Serginio1, Вы писали:

S> Вера это не наш удел. Но вероятность того, что с помощью ИИ можно оптимизировать компиляторы того же C# в С++ вполне реально.

S>Native AOT развиваются, многие библиотеки подтягивают совместимость.
S>Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают.

Вроде unsafe появился, можно писать в цпп стиле на шарпе.
Кодом людям нужно помогать!
Re[4]: Microsoft исключит C++ к 2030 году...
От: mike_rs Россия  
Дата: 25.12.25 10:01
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>На которого свялят неудачу всей этой затеи?


традиционно, найдется фатальный недостаток
Re: Microsoft исключит C++ к 2030 году...
От: mike_rs Россия  
Дата: 25.12.25 10:04
Оценка:
Здравствуйте, Shmj, Вы писали:

S>Верите?


Для начала надо понять, о какой части системы идет речь. Kernel-mode, где ядро/драйвера? User-mode уровень самой ОС (ntdll/kernel32)? Прикладное ПО типа гуя/офиса/что-там-у-них-еще?
Re[3]: Microsoft исключит C++ к 2030 году...
От: ononim  
Дата: 25.12.25 10:05
Оценка:
S>>Native AOT развиваются, многие библиотеки подтягивают совместимость.
S>>Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают.
S>Вроде unsafe появился, можно писать в цпп стиле на шарпе.
пусть еще добавят цпп синтаксис, вместо этого нитакуси, и можно будет использовать)
Как много веселых ребят, и все делают велосипед...
Re[3]: Microsoft исключит C++ к 2030 году...
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 25.12.25 10:11
Оценка:
Здравствуйте, Sharov, Вы писали:

S>> Вера это не наш удел. Но вероятность того, что с помощью ИИ можно оптимизировать компиляторы того же C# в С++ вполне реально.

S>>Native AOT развиваются, многие библиотеки подтягивают совместимость.
S>>Возможно стоило бы расширить C# для создания объектов на стеке. Структуры к сожалению многого не поддерживают.

S>Вроде unsafe появился, можно писать в цпп стиле на шарпе.


Ну я давно unsafe не пользовался. Все зависит от компилятора, unsafe использовали в большинстве для ускорения кода.
Сейчас Native AOT компилирует C# через IL в C++.
Что касается топика, то можно C++ компилировать в промежуточный язык типа IL, а из него в Rust.
C# очень хорошо декомпилируется.
и солнце б утром не вставало, когда бы не было меня
Re[4]: Microsoft исключит C++ к 2030 году...
От: Артём Австралия жж
Дата: 25.12.25 10:39
Оценка: +1
Здравствуйте, Pzz, Вы писали:

Pzz>Ну так взял бы что-нибудь безопасное. Типа, рефакторинг говнокода с помощью ИИ. А не "взять — переписать". Ясно же, что не перепишет. А при этом взялся.

Насчёт что прямо кодовая база у MS это говнокод — очень сомневаюсь. Скорее наоборот, AI там накодит перлов.
Счас помимо моды на AI также мода на вытеснение C/C++ из системного кода, замену на Rust. Пока ещё Бидон был при власти — какой-то даже закон протолкнули, что нужно уже, пора.

Аё>>Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".


Pzz>Как их отличить-то, коммиты с ИИ от коммитов, написанных руками?

Ментальный высер, не имеющий смысла, обильно покрытый комментариями. Я с этим столкнулся, да. Но я же не умею готовить. И кстати, в противовес AI генераторам также и продают AI-детекторы чтоб ловить студентов, так что даже и инструменты есть.

Вроде бы, если ввести документацию в markup там же в репке, развивать её с помощью AI же, вести ревизии и т.п., тогда результат AI намного меньше галлюцинирует в % соотношении от полезного кода — https://rsdn.org/forum/job/9017433.flat
Автор: Артём
Дата: 12.11 14:11
.
Re[5]: Microsoft исключит C++ к 2030 году...
От: sergii.p  
Дата: 25.12.25 13:17
Оценка:
Здравствуйте, Shmj, Вы писали:

S>В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.


ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо.
В Rust хватает вещей которые совсем не реализованы и вот тогда действительно приходится извращаться. А как раз ООП реализовано довольно полно. Это же не Haskell. Вам даже мутировать не запрещают. Попрограммируйте на Haskell, потом вернитесь на Rust — рыдать будете от счастья.
Re[6]: Microsoft исключит C++ к 2030 году...
От: so5team https://stiffstream.com
Дата: 25.12.25 14:22
Оценка:
Здравствуйте, sergii.p, Вы писали:

S>>В общем — слишком сложный для восприятия ООП-код получается. Не пригодно для промышленного использования.


SP>ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо.

SP>В Rust хватает вещей которые совсем не реализованы и вот тогда действительно приходится извращаться. А как раз ООП реализовано довольно полно. Это же не Haskell. Вам даже мутировать не запрещают. Попрограммируйте на Haskell, потом вернитесь на Rust — рыдать будете от счастья.

Мне тут давеча пришлось делать что-то вроде:
class abstract_reader {
public:
  virtual ~reader();

  int get_a() const = 0;
  int get_b() const = 0;
  ... // и еще ряд чистых абстрактных методов.
};

class abstract_mutator : public abstract_reader {
public:
  void set_a(int v) = 0;
  void set_b(int v) = 0;
  ... // и еще ряд чистых абстрактных методов.
};

class basic_impl {
protected:
  int calculate_a() const = 0;
  int calculate_b() const = 0;
  ... // и еще ряд абстрактных методов.

  int impl_get_a() const {
    ... // какая-то логика, в которой вызывается calculate_a.
  }
  int impl_get_b() const {
    ... // какая-то логика, в которой вызывается calculate_b.
  }
  ... // Еще сколько-то реализаций.

  void helper_1() { ... }
  void helper_2() { ... }
  ... // Еще сколько-то вспомогательных методов.

private:
  ... // какие-то данные класса.
};

class reader
  : public abstract_reader
  , protected basic_impl
{
public:
  int get_a() const override { return impl_get_a(); }
  int get_b() const override { return impl_get_b(); }
  ... // остальные методы из abstract_reader.

protected:
  // В реализациях этих методов используются helper_* из basic_impl.
  int calculate_a() const override { ... }
  int calculate_b() const override { ... }
  ... // остальные методы из basic_impl.

private:
  ... // какие-то данные класса.
};


class mutator
  : public abstract_mutator
  , protected basic_impl
{
public:
  int get_a() const override { return impl_get_a(); }
  int get_b() const override { return impl_get_b(); }
  ... // остальные методы из abstract_reader.

  void set_a(int v) override { ... }
  void set_b(int v) override { ... }
  ... // остальные методы из abstract_mutator.

protected:
  // В реализациях этих методов используются helper_* из basic_impl.
  int calculate_a() const override { ... }
  int calculate_b() const override { ... }
  ... // остальные методы из basic_impl.

private:
  ... // какие-то данные класса.
};


Т.е. основной фокус в том, что большая часть общей логики reader/mutator была собрана внутри basic_impl. Причем в basic_impl нужны были специальные "точки кастомизации", которые были представлены виртуальными методами, а реализовывались эти методы в наследниках. Эта общая логика подмещивалась в reader/mutator через наследование от basic_impl.

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

Интересно что бы пришлось делать в Rust-е? Реально интересно, без сарказма.
Re[7]: Microsoft исключит C++ к 2030 году...
От: Shmj Ниоткуда  
Дата: 25.12.25 15:08
Оценка:
Здравствуйте, so5team, Вы писали:

S>Интересно что бы пришлось делать в Rust-е? Реально интересно, без сарказма.


Вот что по вашему получилось. C++

  Скрытый текст
// g++ -std=c++20 -O2 -Wall -Wextra -pedantic main.cpp && ./a.out
#include <iostream>
#include <string>
#include <stdexcept>

// --------- Interfaces (abstract_reader / abstract_mutator) ---------

struct abstract_reader {
  virtual ~abstract_reader() = default;

  virtual int get_a() const = 0;
  virtual int get_b() const = 0;
  virtual std::string describe() const = 0;
};

struct abstract_mutator : abstract_reader {
  virtual void set_a(int v) = 0;
  virtual void set_b(int v) = 0;
};

// --------- "basic_impl": common logic + customization points ---------

class basic_impl {
protected:
  // customization points (hooks)
  virtual int calculate_a() const = 0;
  virtual int calculate_b() const = 0;

  int impl_get_a() const {
    helper_validate_ready();
    if (!cache_a_valid_) {
      cache_a_ = helper_mix("A", calculate_a());
      cache_a_valid_ = true;
    }
    return cache_a_;
  }

  int impl_get_b() const {
    helper_validate_ready();
    if (!cache_b_valid_) {
      cache_b_ = helper_mix("B", calculate_b());
      cache_b_valid_ = true;
    }
    return cache_b_;
  }

  std::string impl_describe() const {
    return "a=" + std::to_string(impl_get_a()) + ", b=" + std::to_string(impl_get_b());
  }

  void helper_invalidate_cache() {
    cache_a_valid_ = false;
    cache_b_valid_ = false;
  }

  void helper_set_ready(bool v) { ready_ = v; }

private:
  void helper_validate_ready() const {
    if (!ready_) throw std::logic_error("object is not ready");
  }

  static int helper_mix(const char* tag, int v) {
    int salt = (tag[0] == 'A') ? 10 : 20;
    return v + salt;
  }

private:
  bool ready_ = true;
  mutable bool cache_a_valid_ = false;
  mutable bool cache_b_valid_ = false;
  mutable int cache_a_ = 0;
  mutable int cache_b_ = 0;
};

// --------- reader ---------

class reader final
  : public abstract_reader
  , protected basic_impl
{
public:
  explicit reader(int base) : base_(base) {}

  int get_a() const override { return impl_get_a(); }
  int get_b() const override { return impl_get_b(); }
  std::string describe() const override { return "reader{" + impl_describe() + "}"; }

protected:
  int calculate_a() const override { return base_ * 3 + 1; }
  int calculate_b() const override { return base_ * base_; }

private:
  int base_;
};

// --------- mutator ---------

class mutator final
  : public abstract_mutator
  , protected basic_impl
{
public:
  mutator(int a, int b) : a_(a), b_(b) {}

  int get_a() const override { return impl_get_a(); }
  int get_b() const override { return impl_get_b(); }
  std::string describe() const override { return "mutator{" + impl_describe() + "}"; }

  void set_a(int v) override {
    a_ = v;
    helper_invalidate_cache();
  }

  void set_b(int v) override {
    b_ = v;
    helper_invalidate_cache();
  }

  void set_ready(bool v) { helper_set_ready(v); }

protected:
  int calculate_a() const override { return a_ * 2; }
  int calculate_b() const override { return b_ + 7; }

private:
  int a_;
  int b_;
};

// --------- Demo ---------

static void print_reader(const abstract_reader& r, const char* title) {
  std::cout << title << ": " << r.describe()
            << " (get_a=" << r.get_a()
            << ", get_b=" << r.get_b()
            << ")\n";
}

int main() {
  try {
    reader r{5};
    print_reader(r, "r first");
    print_reader(r, "r second (cached)");

    mutator m{10, 3};
    print_reader(m, "m initial");
    m.set_a(11);
    print_reader(m, "m after set_a(11)");
    m.set_b(100);
    print_reader(m, "m after set_b(100)");

    m.set_ready(false);
    std::cout << "m set_ready(false)\n";

    // Хотим именно "m.get_a(): Exception: ..."
    std::cout << "m.get_a(): ";
    try {
      std::cout << m.get_a() << "\n";
    } catch (const std::exception& e) {
      std::cout << "Exception: " << e.what() << "\n";
    }
  }
  catch (const std::exception& e) {
    std::cout << "Exception: " << e.what() << "\n";
  }
}


Перевод на Rust

  Скрытый текст
// rustc main.rs && ./main
//
// Вывод (по смыслу как в C++ версии):
// r first: reader{a=26, b=45} (get_a=26, get_b=45)
// r second (cached): reader{a=26, b=45} (get_a=26, get_b=45)
// m initial: mutator{a=30, b=30} (get_a=30, get_b=30)
// m after set_a(11): mutator{a=32, b=30} (get_a=32, get_b=30)
// m after set_b(100): mutator{a=32, b=127} (get_a=32, get_b=127)
// m set_ready(false)
// m.get_a(): Exception: object is not ready

use std::cell::Cell;
use std::fmt;

// --------- Error type (instead of C++ exception) ---------

#[derive(Debug, Clone, Copy)]
enum ReadError {
    NotReady,
}

impl fmt::Display for ReadError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ReadError::NotReady => write!(f, "object is not ready"),
        }
    }
}

// --------- Interfaces (abstract_reader / abstract_mutator) ---------

trait Reader {
    fn get_a(&self) -> Result<i32, ReadError>;
    fn get_b(&self) -> Result<i32, ReadError>;
    fn describe(&self) -> Result<String, ReadError>;
}

trait Mutator: Reader {
    fn set_a(&mut self, v: i32);
    fn set_b(&mut self, v: i32);
}

// --------- "basic_impl" state (private base data) ---------

struct BasicState {
    ready: Cell<bool>,

    cache_a_valid: Cell<bool>,
    cache_b_valid: Cell<bool>,
    cache_a: Cell<i32>,
    cache_b: Cell<i32>,
}

impl BasicState {
    fn new() -> Self {
        Self {
            ready: Cell::new(true),
            cache_a_valid: Cell::new(false),
            cache_b_valid: Cell::new(false),
            cache_a: Cell::new(0),
            cache_b: Cell::new(0),
        }
    }

    fn validate_ready(&self) -> Result<(), ReadError> {
        if self.ready.get() {
            Ok(())
        } else {
            Err(ReadError::NotReady)
        }
    }

    fn set_ready(&self, v: bool) {
        self.ready.set(v);
    }

    fn invalidate_cache(&self) {
        self.cache_a_valid.set(false);
        self.cache_b_valid.set(false);
    }
}

// --------- "basic_impl" logic + customization points (hooks) ---------

trait BasicImpl {
    // доступ к "private данным базового класса"
    fn basic(&self) -> &BasicState;

    // hooks
    fn calculate_a(&self) -> i32;
    fn calculate_b(&self) -> i32;

    fn helper_mix(tag: &str, v: i32) -> i32 {
        let salt = match tag {
            "A" => 10,
            "B" => 20,
            _ => 0,
        };
        v + salt
    }

    fn impl_get_a(&self) -> Result<i32, ReadError> {
        self.basic().validate_ready()?;

        if !self.basic().cache_a_valid.get() {
            let v = Self::helper_mix("A", self.calculate_a());
            self.basic().cache_a.set(v);
            self.basic().cache_a_valid.set(true);
        }
        Ok(self.basic().cache_a.get())
    }

    fn impl_get_b(&self) -> Result<i32, ReadError> {
        self.basic().validate_ready()?;

        if !self.basic().cache_b_valid.get() {
            let v = Self::helper_mix("B", self.calculate_b());
            self.basic().cache_b.set(v);
            self.basic().cache_b_valid.set(true);
        }
        Ok(self.basic().cache_b.get())
    }

    fn impl_describe(&self) -> Result<String, ReadError> {
        Ok(format!("a={}, b={}", self.impl_get_a()?, self.impl_get_b()?))
    }

    // "protected helpers"
    fn helper_invalidate_cache(&self) {
        self.basic().invalidate_cache();
    }

    fn helper_set_ready(&self, v: bool) {
        self.basic().set_ready(v);
    }
}

// --------- reader ---------

struct ReaderImpl {
    basic: BasicState,
    base: i32,
}

impl ReaderImpl {
    fn new(base: i32) -> Self {
        Self {
            basic: BasicState::new(),
            base,
        }
    }
}

impl BasicImpl for ReaderImpl {
    fn basic(&self) -> &BasicState {
        &self.basic
    }

    fn calculate_a(&self) -> i32 {
        self.base * 3 + 1
    }

    fn calculate_b(&self) -> i32 {
        self.base * self.base
    }
}

impl Reader for ReaderImpl {
    fn get_a(&self) -> Result<i32, ReadError> {
        self.impl_get_a()
    }

    fn get_b(&self) -> Result<i32, ReadError> {
        self.impl_get_b()
    }

    fn describe(&self) -> Result<String, ReadError> {
        Ok(format!("reader{{{}}}", self.impl_describe()?))
    }
}

// --------- mutator ---------

struct MutatorImpl {
    basic: BasicState,
    a: i32,
    b: i32,
}

impl MutatorImpl {
    fn new(a: i32, b: i32) -> Self {
        Self {
            basic: BasicState::new(),
            a,
            b,
        }
    }

    fn set_ready(&self, v: bool) {
        self.helper_set_ready(v);
    }
}

impl BasicImpl for MutatorImpl {
    fn basic(&self) -> &BasicState {
        &self.basic
    }

    fn calculate_a(&self) -> i32 {
        self.a * 2
    }

    fn calculate_b(&self) -> i32 {
        self.b + 7
    }
}

impl Reader for MutatorImpl {
    fn get_a(&self) -> Result<i32, ReadError> {
        self.impl_get_a()
    }

    fn get_b(&self) -> Result<i32, ReadError> {
        self.impl_get_b()
    }

    fn describe(&self) -> Result<String, ReadError> {
        Ok(format!("mutator{{{}}}", self.impl_describe()?))
    }
}

impl Mutator for MutatorImpl {
    fn set_a(&mut self, v: i32) {
        self.a = v;
        self.helper_invalidate_cache();
    }

    fn set_b(&mut self, v: i32) {
        self.b = v;
        self.helper_invalidate_cache();
    }
}

// --------- Demo ---------

fn print_reader(title: &str, r: &dyn Reader) {
    // как и в C++: здесь ожидаем, что объект "готов"
    let desc = r.describe().unwrap();
    let a = r.get_a().unwrap();
    let b = r.get_b().unwrap();

    println!("{title}: {desc} (get_a={a}, get_b={b})");
}

fn main() {
    let r = ReaderImpl::new(5);
    print_reader("r first", &r);
    print_reader("r second (cached)", &r);

    let mut m = MutatorImpl::new(10, 3);
    print_reader("m initial", &m);
    m.set_a(11);
    print_reader("m after set_a(11)", &m);
    m.set_b(100);
    print_reader("m after set_b(100)", &m);

    m.set_ready(false);
    println!("m set_ready(false)");

    // хотим ровно как в C++:
    // std::cout << "m.get_a(): ";
    // try { std::cout << m.get_a(); } catch(...) { std::cout << "Exception: ..."; }
    print!("m.get_a(): ");
    match m.get_a() {
        Ok(v) => println!("{v}"),
        Err(e) => println!("Exception: {e}"),
    }
}


Получилось в 1.66 раз больше кода

Т.е. если тупо переписать на Rust — будет больше кода и он будет сложнее. Боюсь что люди не смогут его поддерживать — поддержка тоже на плечи ИИ будет возложена.

См. и мой пример: https://rsdn.org/forum/flame.comp/9036896.1
Автор: Shmj
Дата: 24.12 20:55
=сначала спроси у GPT=
Re[7]: Microsoft исключит C++ к 2030 году...
От: sergii.p  
Дата: 25.12.25 15:20
Оценка: 2 (1)
Здравствуйте, so5team, Вы писали:

S>Интересно что бы пришлось делать в Rust-е? Реально интересно, без сарказма.


так а в чём проблема? Тупо заводишь в ИИ, он тебе генерирует. Я ж про что и говорю: перевод любого ООП кода на Rust не требует выворотов. Простые правила преобразования — с таким ИИ справляется на раз.

pub trait AbstractReader {
    fn get_a(&self) -> i32;
    fn get_b(&self) -> i32;
    // ... остальные методы
}

pub trait AbstractMutator: AbstractReader {
    fn set_a(&mut self, v: i32);
    fn set_b(&mut self, v: i32);
    // ... остальные методы
}

pub trait BasicImpl {
    fn calculate_a(&self) -> i32;
    fn calculate_b(&self) -> i32;
    // ... остальные методы

    fn impl_get_a(&self) -> i32 {
        // ...
    }

    fn impl_get_b(&self) -> i32 {
        // ...
    }

    fn helper_1(&self) {
        // ...
    }

    fn helper_2(&self) {
        // ...
    }
}

// Конкретный Reader
pub struct Reader {
    a: i32,
    b: i32,
    // ... какие-то данные
}

impl BasicImpl for Reader {
    fn calculate_a(&self) -> i32 {
        // ...
    }

    fn calculate_b(&self) -> i32 {
        // ...
    }
}

impl AbstractReader for Reader {
    fn get_a(&self) -> i32 {
        self.impl_get_a()
    }

    fn get_b(&self) -> i32 {
        self.impl_get_b()
    }
    // ... остальные методы
}

// Конкретный Mutator
pub struct Mutator {
    a: i32,
    b: i32,
    // ... какие-то данные
}

impl BasicImpl for Mutator {
    fn calculate_a(&self) -> i32 {
        // ...
    }

    fn calculate_b(&self) -> i32 {
        // ...
    }
}

impl AbstractReader for Mutator {
    fn get_a(&self) -> i32 {
        self.impl_get_a()
    }

    fn get_b(&self) -> i32 {
        self.impl_get_b()
    }
    // ... остальные методы
}

impl AbstractMutator for Mutator {
    fn set_a(&mut self, v: i32) {
        self.a = v;
    }

    fn set_b(&mut self, v: i32) {
        self.b = v;
    }
    // ... остальные методы
}


чем не устраивает? Наоборот, всё по полочкам. Меня например в С++ часто утомляет искать от кого наследуется конкретная функция. Тут всё видно.
Re[8]: Microsoft исключит C++ к 2030 году...
От: so5team https://stiffstream.com
Дата: 25.12.25 15:47
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>
SP>pub trait BasicImpl {
SP>}
SP>


SP>чем не устраивает?


Отсуствие данных в BasicImpl. Дублировать одно и то же в Reader/Mutator -- это не нужная работа, которую приходится делать из-за заморочек Rust-а.

SP> Меня например в С++ часто утомляет искать от кого наследуется конкретная функция. Тут всё видно.


Не так-то просто в impl-е для Reader определить откуда берутся impl_get_a и пр. Хотя, наверное, это дело привычки.
Отредактировано 25.12.2025 15:54 so5team . Предыдущая версия .
Re[4]: Microsoft исключит C++ к 2030 году...
От: ononim  
Дата: 25.12.25 15:55
Оценка:
Аё>>Тем временем, часть open source проектов явно запретили коммиты с говно эй ай с мотивацией "мейнтейнерам нет желания читать тонны говнокода".
Pzz>Как их отличить-то, коммиты с ИИ от коммитов, написанных руками?
Очень отличается громоздкостью кода. Практически всегда можно написать раз в 10 лаконичнее и понятнее. Но — не спорю что это займет у мясных заметно больше времени. Про доводы что код должен быть в первую очередь читабелен все както и забыли как будто.
Вобщем, индустрию накрывает большой макаронный монстр пипец.
Как много веселых ребят, и все делают велосипед...
Отредактировано 25.12.2025 15:58 ononim . Предыдущая версия .
Re[6]: Microsoft исключит C++ к 2030 году...
От: Shmj Ниоткуда  
Дата: 25.12.25 16:04
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>ну мне выглядит ок. Чего сложного? Интерфейс явно выделен. Реализация максимально отделена. Дело привычки. Всё реализуемо.


Там приходится лишнюю работу делать — для каждого метода явно уточнять от какого наследника он тянется. А представьте что таких методов сотни? Дурная работа.

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