Russian Qt Forum
Апрель 30, 2024, 16:23 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: cow_ptr (полиморфная шара)?  (Прочитано 13336 раз)
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« : Февраль 06, 2017, 12:20 »

Добрый день

Навеяно соседней темой. Простой пример имплисит шары
Код
C++ (Qt)
struct SomeClass {
..
QImage m_data;
..
};
И все здесь очень хорошо. И конструктор/деструктор по умолчанию, и isNull есть, и копируется по-умному. Но вот беда - m_data не может быть полиморфной, это только QImage и ничто иное. Нельзя ли это как-то (творчески) переработать в умный указатель чтобы иметь возможность
Код
C++ (Qt)
cow_ptr<SomeData> m_data;
...
m_data = new SomeDerivedData;
Т.е. тот же ф-ционал имплисит шары но с возможностью полиморфизма. Или это фантастика?

Спасибо
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #1 : Февраль 06, 2017, 12:27 »

Если вместо QImage использовать QVariant, то возможен динамический полиморфизм.
Записан
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #2 : Февраль 06, 2017, 12:38 »

Еще можно использовать boost::any, который должен войти в C++17, как std::any.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #3 : Февраль 06, 2017, 12:43 »

Вариант и эни не то, что нужно, они не дают корову.
Написать такой указатель можно (2мя способами - через наследование от интерфейса с методом clone() либо через мета-объектную систему, выцеплять конструктор копирования).
Не очень понятно, правда, какую задачу решает данный указатель.
Корова эмулирует value-based типы (которые копируются на стеке).
Шаред-птр и юник-птр (и любой другой птр) хранят указатели на уникальный объект (который не должен копироваться).
В чем смысл клонировать объект?

Upd: ну только могу придумать когда внешне это всё тот же value-based, а внутри полиморфная приватная дата (например, зависит от платформы, хз). Это делается через пару QSharedDataPointer на дату + std::unique_ptr на полиморфную часть в этой дате.
« Последнее редактирование: Февраль 06, 2017, 12:44 от Авварон » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #4 : Февраль 06, 2017, 13:03 »

Не очень понятно, правда, какую задачу решает данный указатель.
Ту же самую (корову) что исходный пример с QImage но не завязан жестко на этот тип

Шаред-птр и юник-птр (и любой другой птр) хранят указатели на уникальный объект (который не должен копироваться).
У них не должен, у нас должен (при записи).
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #5 : Февраль 06, 2017, 13:31 »

Если вместо QImage использовать QVariant, то возможен динамический полиморфизм.
Еще можно использовать boost::any, который должен войти в C++17, как std::any.
Задача иметь обычный ф-ционал указателя (может указывать как на базовый тип так и на порожденный) но "одетый" в удобную оболочку вумного указателя. Хранить "все на свете" планов не было
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #6 : Февраль 06, 2017, 13:38 »

Это не задача
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #7 : Февраль 06, 2017, 14:16 »

Кажется, эта задача решается с помощью python
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #8 : Февраль 06, 2017, 15:08 »

Что-то плохо доходит. Еще раз. Вот мы написали так
Код
C++ (Qt)
struct SomeClass {
..
QImage m_data;
..
};
И все хорошо. Но вот выясняется что в одном из вариантов понадобился не QImage а его потомок напр MyImage. Наши действия?
Код
C++ (Qt)
QSharedPointer<QImage> m_data;
 
Но это совсем не то что нужно. Мы хотели имплисит шару, а не "уникальность". Да, копии SomeClass могут иметь свои копии m_data в рез-те их редактирования, никакой "общий ресурс" в наши планы не входил. А тут приходится объявлять шаред который совсем не шаред, а потом латать копирование для SomeClass  Плачущий
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #9 : Февраль 06, 2017, 15:38 »

Ещё раз - какую задачу вы решаете?
COW решает задачу дешевого копирования объектов на стеке. То, что там внутри указатель мы знать не должны (просто абстракция весьма дырявая, поэтому приходиться знать как оно "под капотом").
shared_ptr решает задачу раздельного владения уникальным объектом.
unique_ptr решает задачу уникального владения уникальным объектом.
Что вы хотите сделать? Пример с куимаджем нерелевантен почти полностью, так как у него нет даже виртуальных методов (на самом деле, есть, но это врядли). Какой полиморфизм вы хотите от класса без виртуальных методов?
Записан
Пантер
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 5876


Жаждущий знаний


Просмотр профиля WWW
« Ответ #10 : Февраль 06, 2017, 15:47 »

Igors, ты хочешь утиную типизацию?

Код
C++ (Qt)
class A {virtual foo () = 0;};
class B : public A {virtual foo() {};};
 
struct C
{
 C () : a (new B) {}
 A *a;
}
 
 

Но чтобы a была на стеке? Шаблон тогда нужен.
Записан

1. Qt - Qt Development Frameworks; QT - QuickTime
2. Не используйте в исходниках символы кириллицы!!!
3. Пользуйтесь тегом code при оформлении сообщений.
ssoft
Программист
*****
Offline Offline

Сообщений: 579


Просмотр профиля
« Ответ #11 : Февраль 06, 2017, 15:48 »

Проблема QImage и других подобных типов, что они реализуют implicit shared внутри, и не очень то располагают к дальнейшему наследованию. В случае Qt наследоваться приходится от скрытой приватной части, что мягко говоря неудобно.

А вообще можно использовать (написать самостоятельно) умный указатель, реализующий implicit shared технику, тогда корова останется коровой.

Код
C++ (Qt)
implicit_shared_ptr< Cow > cow = implicit_shared_ptr< MyCow >::make();
 

Внутри implicit_shared_ptr скроется непосредственно share_ptr и метод detach(), реализующий клонирование MyCow.
Так как предполагается клонирование экземпляра произвольного типа MyCow, то хранить придется не сам тип, а обертку Holder поверх его (подобно boost::any).
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #12 : Февраль 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.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #13 : Февраль 06, 2017, 16:46 »

Еще упростим (стоит статУя вообще без плюсов)
Код
C++ (Qt)
struct SomeClass {
..
BaseData * m_data;   // указатель на базовый класс
..
};
 
Типовая ситуация: SomeClass владеет BaseData и копии SomeClass имеют свои копии BaseData. Хотелось бы объявить m_data просто членом, но не выходит т.к. он полиморфный. Приходится объявлять указателем, тогда получаем серию мелких (пусть и не смертельных) забот - об этом указателе надо заботиться в конструкторе, деструкторе и при копировании. Также хотелось бы иметь корову на копировании. Вот собсно вся задача, что тут неясно Непонимающий

И вот я как-то не вижу как ее решить стандартными средствами. Все уперлись рогом в "уникальность", как будто других потребностей нет.

Проблема QImage и других подобных типов, что они реализуют implicit shared внутри, и не очень то располагают к дальнейшему наследованию.
Да, тоже думал об этом, прошивать методы ref/deref как-то не тянет, да и хотелось бы класс-содержимое в это не посвящать. Если вумный указатель, то все проходит через операторы ->, *, ну может и сделать их константными, а для записи юзать get() или data() и там расшаривать. Потому что так
Код
C++ (Qt)
template<class T>
struct cow_ptr {
...
T * operator -> ( void );
const T * operator -> ( void ) const;
...
};
 
cow_ptr<SomeData> ptr(new SomeData);
int a = ptr->mA;   // позовет неконстантный ->, сволочь такая
 
« Последнее редактирование: Февраль 06, 2017, 16:55 от Igors » Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3258


Просмотр профиля
« Ответ #14 : Февраль 06, 2017, 16:58 »

Еще упростим (стоит статУя вообще без плюсов)
Типовая ситуация: SomeClass владеет BaseData и копии SomeClass имеют свои копии BaseData. Хотелось бы объявить m_data просто членом, но не выходит т.к. он полиморфный. Приходится объявлять указателем, тогда получаем серию мелких (пусть и не смертельных) забот - об этом указателе надо заботиться в конструкторе, деструкторе и при копировании. Также хотелось бы иметь корову на копировании. Вот собсно вся задача, что тут неясно Непонимающий

И вот я как-то не вижу как ее решить стандартными средствами. Все уперлись рогом в "уникальность", как будто других потребностей нет.


Ну, это не решается стандартными средствами, потому что вы хотите 1 стандартное и 1 нестандартное средство совместить в одно.
Первое - нужен "вумный" указатель, который полиморфно клонирует объект
Код
C++ (Qt)
template<class T>
class MyPtr
{
   T *d;
   MyPtr(const MyPtr &other) : d(other.d->clone()) {}
};
 
Второе - собсно обычная корова (QSharedData+QSharedDataPointer), которая управляет МуПтром.
Код
C++ (Qt)
class SomeClass {
   SomeClassData : public QSharedData
   {
        MyPtr<BaseData> data;
   };
 
    QSharedPointer<SomeClassData> d;
};
 

И да, это уже 3й раз когда решение называется в этом треде.
« Последнее редактирование: Февраль 06, 2017, 17:01 от Авварон » Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.216 секунд. Запросов: 22.