Constantine
Какой профит из этого?
А теперь у меня дерево наследования глубины 4, и этот метод вызывается самим классом. Набросаете пример?
Anatoly
держи struct Base { virtual ~Base() {}; virtual std::shared_ptr<Base> clone() = 0; //сейчас работает с Base* }; struct Derived : Base { std::shared_ptr<Derived> clone() override = 0; //сейчас работает с Derived* };
ну я могу предложить work around: struct Base { virtual ~Base() {}; private: virtual std::shared_ptr<Base> clone() = 0; }; struct Derived : Base { std::shared_ptr<Base> clone() override { return concrete_clone(); } std::shared_ptr<Derived> concrete_clone() { return std::make_shared<Derived>(*this); } };
Egor
https://stackoverflow.com/a/197157/767632
Egor
Говорят, что нельзя
Egor
Вот была бы Scala...
Constantine
я знаю, что нельзя просто так, вопрос нельзя ли это с модификацией языка сделать)
Constantine
я понимаю, что там делается шаманская магия компилятором, чтобы эти типы работали
Egor
Можно сделать виртуальные функции приватными, а публичные делать с нужным интерфейсом и скрывать
Constantine
собственно говоря я полагаю, что вызывающий Derived делает implicit type cast
Constantine
Можно сделать виртуальные функции приватными, а публичные делать с нужным интерфейсом и скрывать
Да обходы тут есть, еще можно по сути заставить supa_shared_ptr клонированием заниматься
Constantine
Если аллокатор при создании в него записывать
Egor
https://pastebin.com/jj4rhBt3
Egor
Ну типа вот
Constantine
https://pastebin.com/jj4rhBt3
вот такая реализация подозрительна, static_cast штука неприятная
Egor
Можно dynamic_cast, сейчас ещё подумаю
Constantine
Я не очень понимаю, чем это мешает сделать поинтеры на Base везде
Потому что после clone() каждый объект себя тайпкастит
Constantine
Можно dynamic_cast, сейчас ещё подумаю
Там Анатолий выше показывал схему, которая типы не теряет
Constantine
Хотя если метаклассы будут, твоя схема реализуется шикарно (вся проблема в возможности криво написать тип возвращаемого clone())
Constantine
Да, есть еще один вопрос. Вот enable_shared_from_this очень плохо дружит с наследованием, а в чем проблема namespace std { template <typename T> std::shared_ptr<T> shared_from(T* that) /*requires (T has unambigious public base enable_shared_from_this<BaseOfT> ) */ { return static_pointer_cast<T>(that->shared_from_this()); } } //usage: std::shared_from(this); std::shared_from(that);
Constantine
pointer_cast же
я там криво выразился, следующие сообщения разъясняют вопрос
Constantine
Самим классом это каким?
Derived хочет копироваться
Max
Derived хочет копироваться
Подгони ему пару 😂
Constantine
Подгони ему пару 😂
Все есть, но вот ребенок по заявке - примат
Max
Derived хочет копироваться
А нельзя сделать отдельный клас, как вариат, задача которого будет клонировать любые обьекты, унаследованные от Base?
Max
А как ретипизировать?
Задача в том, чтобы имея поинтер на обьект одного проиводного типа (по иерархии, например третий из пяти по дереву), клонировать его и получить такой же обьект того же типа, верно?
Constantine
Задача в том, чтобы имея поинтер на обьект одного проиводного типа (по иерархии, например третий из пяти по дереву), клонировать его и получить такой же обьект того же типа, верно?
Задача: находясь внутри функции - члена (полиморфного) класса вызвать функцию клонирования без потери информации о типе (результата)
Berkus
ну по идее static_pointer_cast<Derived>(clone())
Max
ну по идее static_pointer_cast<Derived>(clone())
ну я уже это предлагал, но он как раз хочет сберечь тип
Max
Задача: находясь внутри функции - члена (полиморфного) класса вызвать функцию клонирования без потери информации о типе (результата)
А почему именно функция-член класса? Почему не любая другая, которая примет указатель на обьект данного класа?
Berkus
ну можно взять язык с контравариантными по возврату функциями и наслаждаться
Constantine
ну можно взять язык с контравариантными по возврату функциями и наслаждаться
возможность использовать язык программирования, а не С++, имеется по умолчанию ;)
Constantine
в расте поправлено?)
Constantine
хотя как я понимаю, в расте вообще нет полиморфизма в виде наследования С++
Berkus
есть, но на трейтах
Aidar
есть, но на трейтах
утиная типизация не всегда правильно работает
Berkus
я не знаю, о чем ты говоришь
Berkus
статический полиморфизм продвигаешь в массы? а как же virtual?
Aidar
статический полиморфизм продвигаешь в массы? а как же virtual?
ну я имел ввиду намешать и сделать 2 версии
Constantine
а наследовать как
Constantine
это не ты там enable_shared_from_this придумал?)
Aidar
а наследовать как
наследуешь то только clonable
Constantine
наследуешь то только clonable
мну иерархия чутка сложнее одного интерфейса clonable
Berkus
ну это просто пример
ну он ломается же при наличии наследования и виртуальных функций
Александр
https://www.reddit.com/r/cpp/comments/7c208c/is_constexpr_a_macro_that_check_if_an_expression/
Stanislav
Berkus
ну, например, если бы захотел. у меня был например очень практический случай когда без аллокатора было никак. хотел использовать стандартный контейнер но не было никакой памяти - ни мемори менеджера, ни стандартной либы, ничего.
Stanislav
шальной геймдев какой нибудь)
Egor
Вот есть полезное применение: https://developers.google.com/protocol-buffers/docs/reference/arenas Грубо говоря, создаём на запрос X МБ памяти и забиваем на удаление объектов, фрагментацию и прочее, выделяем методом "сдвинуть указатель", а в конце запроса убиваем кусок один махом.
Egor
Еще вариант: захотелось ускорить решение олимпиадной задачи на десяток процентов. Тогда делаем глобальную арену и забиваем на удаление памяти просто перегрузкой operator new. Это, конечно, не аллокатор.
Egor
1. Попробовали стандартный. 2. Кончилась память из-за фрагментации. 3. Написали свои SLAB'ы или что-то похожее для мелких объектов.
Egor
1. Попробовали стандартный. 2. Тормозит выделение/удаление. 3. Увидели хороший паттерн в своём использовании памяти (скажем, там стэк/очередь). 4. Написали свой.
Egor
Думаю, да. Например, ежели нужны строгие гарантии того, что, как и сколько времени работает. Скажем, нужен realtime. Тогда надо гарантировать realtime-аллокации.
Berkus
...в реалтайме
Egor
Или если имеется общеизвестный факт про то, что стандартный аллокатор в конкретном компиляторе, который у меня есть — отстой. Ну, скажем, фрагментируется как отстой и всё падает. Скажем, я с примерно этим в Delphi 7 встречался. Ну или если я в качестве упражнения хочу написать что-то вот прям охренеть адски быстрое и считаю, что мои паттерны использования памяти достаточно нерандомны (а так, небось, в 99% случаев), чтобы с ними можно было что-то сделать.
Egor
Ну, такое. Разумеется, насколько быстрым оно будет, заранее не сказать, но добавлять себе разрешения использовать стандартный аллокатор намного проще, чем в какой-то момент этот стандартный выпиливать. Примерно как проще, имхо, с самого начала написать на C без абстракций, чем сначала на плюсах, а потом перейти на C и выпиливать абстракции.
Egor
Просто потому что простые в написании абстракции и удобные в использовании абстракции — это разные вещи.
Ioann_
А тут, по Qt - никто не подскажет :? А то в чатце по Qt что-то тишь
Anton
Я бы стал писать свой аллокатор ровно тогда, когда захотел по максимуму использовать ровно один большой блок на своё приложение. Эдакое ограничение сверху. Естесвенно, это аллокатор-синглтон.
Egor
"Сначала измерять, а потом решать" — хороший подход, но если надо прям ужиматься во время и память, то стандартная библиотека обычно всё-таки не так эффективна, как можно было бы сделать в конкретном коде. Скажем, результаты измерений могут показать, что тормозит равномерно весь код из-за дутых абстракций, и тогда выпиливание какой-то одной вообще эффекта не даст, надо выпиливать десятками и перелопачивать архитектуру.
Egor
Зависит от языка, конечно, и в плюсовой библиотеке довольно много хороших мест.
Anton
Нет. Прикол в том, чтобы помимо стека иметь один большой блок памяти. Просто инстансы контейнерных аллокаторов будут обращаться к глобальному, который хранит в себе тот выделенный блок.
Egor
Ах да, конечно: ещё можно писать свой аллокатор, если у тебя lock-free структуры данных. Тогда нужна хитрая сборка мусора.
Egor
Очень, очень сильно сомневаюсь, у меня слишком мало опыта и понимания в том, какие вообще паттерны доступа и запросы есть у рандомного приложения.
Anton
Ну, дыа.