Название: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 06, 2017, 12:20 Добрый день
Навеяно соседней темой. Простой пример имплисит шары Код И все здесь очень хорошо. И конструктор/деструктор по умолчанию, и isNull есть, и копируется по-умному. Но вот беда - m_data не может быть полиморфной, это только QImage и ничто иное. Нельзя ли это как-то (творчески) переработать в умный указатель чтобы иметь возможность Код Т.е. тот же ф-ционал имплисит шары но с возможностью полиморфизма. Или это фантастика? Спасибо Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 06, 2017, 12:27 Если вместо QImage использовать QVariant, то возможен динамический полиморфизм.
Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 06, 2017, 12:38 Еще можно использовать boost::any, который должен войти в C++17, как std::any.
Название: Re: cow_ptr (полиморфная шара)? Отправлено: Авварон от Февраль 06, 2017, 12:43 Вариант и эни не то, что нужно, они не дают корову.
Написать такой указатель можно (2мя способами - через наследование от интерфейса с методом clone() либо через мета-объектную систему, выцеплять конструктор копирования). Не очень понятно, правда, какую задачу решает данный указатель. Корова эмулирует value-based типы (которые копируются на стеке). Шаред-птр и юник-птр (и любой другой птр) хранят указатели на уникальный объект (который не должен копироваться). В чем смысл клонировать объект? Upd: ну только могу придумать когда внешне это всё тот же value-based, а внутри полиморфная приватная дата (например, зависит от платформы, хз). Это делается через пару QSharedDataPointer на дату + std::unique_ptr на полиморфную часть в этой дате. Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 06, 2017, 13:03 Не очень понятно, правда, какую задачу решает данный указатель. Ту же самую (корову) что исходный пример с QImage но не завязан жестко на этот типШаред-птр и юник-птр (и любой другой птр) хранят указатели на уникальный объект (который не должен копироваться). У них не должен, у нас должен (при записи). Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 06, 2017, 13:31 Если вместо QImage использовать QVariant, то возможен динамический полиморфизм. Еще можно использовать boost::any, который должен войти в C++17, как std::any. Задача иметь обычный ф-ционал указателя (может указывать как на базовый тип так и на порожденный) но "одетый" в удобную оболочку вумного указателя. Хранить "все на свете" планов не былоНазвание: Re: cow_ptr (полиморфная шара)? Отправлено: Авварон от Февраль 06, 2017, 13:38 Это не задача
Название: Re: cow_ptr (полиморфная шара)? Отправлено: __Heaven__ от Февраль 06, 2017, 14:16 Кажется, эта задача решается с помощью python
Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 06, 2017, 15:08 Что-то плохо доходит. Еще раз. Вот мы написали так
Код
Код Но это совсем не то что нужно. Мы хотели имплисит шару, а не "уникальность". Да, копии SomeClass могут иметь свои копии m_data в рез-те их редактирования, никакой "общий ресурс" в наши планы не входил. А тут приходится объявлять шаред который совсем не шаред, а потом латать копирование для SomeClass :'( Название: Re: cow_ptr (полиморфная шара)? Отправлено: Авварон от Февраль 06, 2017, 15:38 Ещё раз - какую задачу вы решаете?
COW решает задачу дешевого копирования объектов на стеке. То, что там внутри указатель мы знать не должны (просто абстракция весьма дырявая, поэтому приходиться знать как оно "под капотом"). shared_ptr решает задачу раздельного владения уникальным объектом. unique_ptr решает задачу уникального владения уникальным объектом. Что вы хотите сделать? Пример с куимаджем нерелевантен почти полностью, так как у него нет даже виртуальных методов (на самом деле, есть, но это врядли). Какой полиморфизм вы хотите от класса без виртуальных методов? Название: Re: cow_ptr (полиморфная шара)? Отправлено: Пантер от Февраль 06, 2017, 15:47 Igors, ты хочешь утиную типизацию?
Код
Но чтобы a была на стеке? Шаблон тогда нужен. Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 06, 2017, 15:48 Проблема QImage и других подобных типов, что они реализуют implicit shared внутри, и не очень то располагают к дальнейшему наследованию. В случае Qt наследоваться приходится от скрытой приватной части, что мягко говоря неудобно.
А вообще можно использовать (написать самостоятельно) умный указатель, реализующий implicit shared технику, тогда корова останется коровой. Код
Внутри implicit_shared_ptr скроется непосредственно share_ptr и метод detach(), реализующий клонирование MyCow. Так как предполагается клонирование экземпляра произвольного типа MyCow, то хранить придется не сам тип, а обертку Holder поверх его (подобно boost::any). Название: Re: cow_ptr (полиморфная шара)? Отправлено: Авварон от Февраль 06, 2017, 15:54 Igors, ты хочешь утиную типизацию? Вот и я пытаюсь добиться, чего хоцца. В такой постановке уже 2 человека написали - коровный указатель, к-ый вызывает clone() у объекта когда надо. Цитировать If it walks like a duck, and quacks like a duck, it’s probably gonna throw exceptions at runtime. Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 06, 2017, 16:46 Еще упростим (стоит статУя вообще без плюсов)
Код Типовая ситуация: SomeClass владеет BaseData и копии SomeClass имеют свои копии BaseData. Хотелось бы объявить m_data просто членом, но не выходит т.к. он полиморфный. Приходится объявлять указателем, тогда получаем серию мелких (пусть и не смертельных) забот - об этом указателе надо заботиться в конструкторе, деструкторе и при копировании. Также хотелось бы иметь корову на копировании. Вот собсно вся задача, что тут неясно ??? И вот я как-то не вижу как ее решить стандартными средствами. Все уперлись рогом в "уникальность", как будто других потребностей нет. Проблема QImage и других подобных типов, что они реализуют implicit shared внутри, и не очень то располагают к дальнейшему наследованию. Да, тоже думал об этом, прошивать методы ref/deref как-то не тянет, да и хотелось бы класс-содержимое в это не посвящать. Если вумный указатель, то все проходит через операторы ->, *, ну может и сделать их константными, а для записи юзать get() или data() и там расшаривать. Потому что такКод
Название: Re: cow_ptr (полиморфная шара)? Отправлено: Авварон от Февраль 06, 2017, 16:58 Еще упростим (стоит статУя вообще без плюсов) Типовая ситуация: SomeClass владеет BaseData и копии SomeClass имеют свои копии BaseData. Хотелось бы объявить m_data просто членом, но не выходит т.к. он полиморфный. Приходится объявлять указателем, тогда получаем серию мелких (пусть и не смертельных) забот - об этом указателе надо заботиться в конструкторе, деструкторе и при копировании. Также хотелось бы иметь корову на копировании. Вот собсно вся задача, что тут неясно ??? И вот я как-то не вижу как ее решить стандартными средствами. Все уперлись рогом в "уникальность", как будто других потребностей нет. Ну, это не решается стандартными средствами, потому что вы хотите 1 стандартное и 1 нестандартное средство совместить в одно. Первое - нужен "вумный" указатель, который полиморфно клонирует объект Код Второе - собсно обычная корова (QSharedData+QSharedDataPointer), которая управляет МуПтром. Код
И да, это уже 3й раз когда решение называется в этом треде. Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 07, 2017, 12:01 Набросал на скорую руку такое решение.
Такое поведение имелось в виду? Код
Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 07, 2017, 13:35 Первое - нужен "вумный" указатель, который полиморфно клонирует объект А разве такое клонирование полиморфно? По-моему нет, ведь other может быть лишь того же типа T. Поправьте если не такКод
Второе - собсно обычная корова (QSharedData+QSharedDataPointer), которая управляет МуПтром. Да, но делегировать на "d" хлопотно. Сравним с "нулевым вариантом" (голый указатель). В принципе и там все решаемо за 5-10 минут. Ну добавил по строчке в конструктор/деструктор. С копированием правда хужее - придется считать что BaseData имеет виртуальный метод clone(). Вот когда все эти сопельки убираются "легким движением руки" - гуд. А начинать долгую писанину из-за этого непривлекательно.Набросал на скорую руку такое решение. К сожалению, все никак не переползу на С++ 11, но по тексту вижу - да, такое. Никак нельзя убрать (или иначе оформить) эти readable/writeable? Спасибо Такое поведение имелось в виду? Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 07, 2017, 14:17 Набросал на скорую руку такое решение. К сожалению, все никак не переползу на С++ 11, но по тексту вижу - да, такое. Никак нельзя убрать (или иначе оформить) эти readable/writeable? Спасибо Такое поведение имелось в виду? Для ранних С++ тоже можно написать решение, только кода будет значительно больше, в основном из-за "_Arguments ... args". Сделать основу? Совсем от readable/writable избавиться не получится. Либо придется следить за const так Код
Либо так Код
Либо так Код
Либо как изначально Код
Выберете один из. Мне больше нравится третий, так как этот вариант легче всего переопределить под произвольный тип (как std::begin/std::end). Но это мое субъективное мнение. Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 07, 2017, 14:58 Для QSharedPointer и более ранних С++
Код
Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 08, 2017, 08:48 ...в основном из-за "_Arguments ... args". Сделать основу? Спасибо, не нужно, эти "вариадики" меня так пугают...А вот такая (экспериментальная) мысль - а не задействовать ли и здесь weak_ptr (вероятно его аналог). Guard - ценная возможность, ну может detach при его создании... Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 08, 2017, 15:54 А вот такая (экспериментальная) мысль - а не задействовать ли и здесь weak_ptr (вероятно его аналог). Guard - ценная возможность, ну может detach при его создании... Implicit shared обертка реализует Так как Касаясь вопроса применения weak_ptr во внутренней реализации обертки, то weak_ptr не реализует агрегацию в принципе - ни композитную, ни обобщенную. weak_ptr реализует ассоциативную связь с возможностью продления времени жизни экземпляра объекта, поэтому в данном месте неприменим. Необходимо отметить, что для экземпляров объектов под управлением Implicit shared не существует возможности сослаться любым другим способом, так как они могут быть клонированы в любой момент. Однако имеется возможность ссылки на саму Implicit shared обертку. Название: Re: cow_ptr (полиморфная шара)? Отправлено: ViTech от Февраль 08, 2017, 17:27 Я бы не стал смешивать ассоциации и Implicit shared. По мне, copy-on-write - это просто техника оптимизации хранения и копирования данных объекта, его внутренние проблемы, и не более. Есть ли в объекте cow, нет ли, на логику создания/удаления, владения, связей между объектами, логику модели это никакого влияния оказывать не должно.
Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 08, 2017, 17:42 Я бы не стал смешивать ассоциации и Implicit shared. По мне, copy-on-write - это просто техника оптимизации хранения и копирования данных объекта, его внутренние проблемы, и не более. Есть ли в объекте cow, нет ли, на логику создания/удаления, владения, связей между объектами, логику модели это никакого влияния оказывать не должно. Да, напрямую не стоит смешивать. Я имел всего лишь в виду, что Implicit shared обертка представляет сам объект, как уникальный экземпляр, в то время как он на самом деле обобщенный. А ассоциации здесь относятся к внутренней архитектуре самой обертки, как и весь предыдущий мой пост о возможности применения внутри weak_ptr. Поправлю помарки). Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 08, 2017, 18:58 По мне, copy-on-write - это просто техника оптимизации хранения и копирования данных объекта, его внутренние проблемы, и не более. Есть ли в объекте cow, нет ли, на логику создания/удаления, владения, связей между объектами, логику модели это никакого влияния оказывать не должно. Категорически согласен! Корова может быть пожертвована в любой момент, примерКод: QVector<int> vec; Я бы не стал смешивать ассоциации и Implicit shared. Но почему совершенно противоположный вывод ??? :)Касаясь вопроса применения weak_ptr во внутренней реализации обертки, то weak_ptr не реализует агрегацию в принципе - ни композитную, ни обобщенную. weak_ptr реализует ассоциативную связь с возможностью продления времени жизни экземпляра объекта, поэтому в данном месте неприменим. Мне кажется Вы слишком увлеклись абстракцией :) Есть блочок памяти в котором сидят счетчики и (возможно) хранимый объект. Этот блочок живет пока хотя бы 1 из счетчиков ненулевой. Weak имеет к нему доступ так же как и шаред, просто weak не препятствует удалению объекта. Почему Вы считаете его чем-то принципиально иным?Не очень понял про "агрегацию" и "ассоциацию", если нетрудно поясните что значат эти термины в данном контексте. Спасибо Название: Re: cow_ptr (полиморфная шара)? Отправлено: ssoft от Февраль 08, 2017, 20:47 Не очень понял про "агрегацию" и "ассоциацию", если нетрудно поясните что значат эти термины в данном контексте. Спасибо Это понятия модели ООП. Ассоциация - это понятие означающее, что экземпляры одного класса связаны с экземплярами другого класса. Также вводится понятие связь (link), как экземпляра ассоциации, которая реализуется в виде, включающем понятие полюсов. Полюсы могут являться частью сущностей, участвующих в ассоциации. Если не вдаваться в подробности, то связи (их полюсы) реализуются всяческими указателями, ссылками или вычисляются runtime. Ассоциации бывают бинарными, и т.д. N-нарными, в зависимости от количества участвующих сущностей. Чаще всего мы имеем дело с бинарными ассоциациями. Одним из частных случаев бинарной ассоциации является отношение типа "часть ‒ целое", такие ассоциации имеют название агрегации. В такой ассоциации целым (агрегатором) по отношению к части может быть только одна сущность (правила подобны отношению наследования). Целое может агрегировать часть индивидуально (composite) или совместно (shared). Первый случай часто называют композицией. Отношение "часть - целое" регламентирует удаление части вместе с целым (по крайне мере в композиции). Удобно совместить контроль времени жизни экземпляра объекта с экземпляром полюса, реализующим ассоциативную связь агрегации. Другого вида ассоциативные связи, по моему, логически несовместимы с контролем времени жизни. Хорошо иллюстрирует ассоциативную связь агрегации отношение parent - child, когда child "знает", кто его parent. parent должен обеспечить уникальное владение своими child, а child ссылаться на своего parent. weak_ptr не реализует полюс ассоциативной связи агрегации со стороны целого (так как не управляет временем жизни экземпляра) , хотя может реализовывать полюс ассоциативной связи агрегации со стороны части. Wrapper является целым по отношению к хранимому объекту, таким образом внутреннее представление должно реализовывать полюс ассоциации со стороны целого в любом доступном виде. Название: Re: cow_ptr (полиморфная шара)? Отправлено: Igors от Февраль 09, 2017, 12:23 Ассоциация - это понятие означающее.. Не все, но кое-что понял. Спасибо за разъяснения.Насчет аналога weak_ptr. Посмотрим что с "продлением жизни". Допустим если объект "жив" - увеличиваем число ссылок на него создавая еще один wrapper (cow_ptr). Однако, в отличие от шаред, мы согласились с созданием копии (пусть копирование состоится и не сразу). И можем с копией и остаться, т.е. по сути ничего не продлеваем. Можно конечно действовать по образцу QPointer, так мы получим raw указатель если живой. Что легко может стать источником ошибок. Напр теперь уже нельзя из него делать wrapper. Ну может ограничить аналог weak методами isNull и константным -> Мда, как-то становится неуютно когда нет знакомых вещей :) |