Subclassing QModelIndex - private constructor?
-
@Dariusz said in Subclassing QModelIndex - private constructor?:
when QmodelIndex is deleted
A QModelIndex does not store anything so there can't be deleted anything when a QModelIndex is deleted. A QModelIndex just holds information about a cell and how to get to the underlying data.
-
@Christian-Ehrlicher Given that you store underlying data in vector as std::shared_ptr<treeItem>, how would you pass that to QModelIndex&retrieve it later so that shared_ptr count gets properly managed and you can work with it?
ItemFromIndex() etc?Currently I'm using createIndex(row,col,sharedPtr.get()), but that breaks in many cases for some weird reasons I cant track down :- (
-
Since the QModelIndex does not store any data but just points to the data it a plain pointer is ok.
-
@Christian-Ehrlicher said in Subclassing QModelIndex - private constructor?:
Since the QModelIndex does not store any data but just points to the data it a plain pointer is ok.
Well can it store shared_ptr ?
-
-
@Dariusz said in Subclassing QModelIndex - private constructor?:
Well can it store shared_ptr ?
Once again: A QModelIndex does not store the data so even it you could store a pointer there it would be the wrong way.
-
@Christian-Ehrlicher It stores a pointer to data node, In Qt native case its QStandardItem*. I'm trying to store the same thing but my objects are done via shared_ptr instead of raw pointers.
So again, I kinda need to extend the class or else a way to pass shared_ptr to the void*adata parameter/quintptr.
@kshegunov Is that not good enough reason to expose the constructor to allow users to subclass the QModelIdnex class to allow for a work around to store it?
-
@Dariusz said in Subclassing QModelIndex - private constructor?:
@Christian-Ehrlicher It stores a pointer to data node
First of all, it stores an opaque pointer, which can be any pointer.
I'm trying to store the same thing but my objects are done via shared_ptr instead of raw pointers.
Secondly, this is not a pointer! This is an object that aggregates a pointer. An object, no matter what it contains, isn't a pointer itself.
So again, I kinda need to extend the class or else a way to pass shared_ptr to the void*adata parameter/quintptr.
You can't and you will not. If you want to reference a list of shared pointers, put them in a vector, and store the index of the element inside the model index. When you need to get the shared pointer, take the index of the element from the model index and get the shared pointer from the vector.
@kshegunov Is that not good enough reason to expose the constructor to allow users to subclass the QModelIdnex class to allow for a work around to store it?
No. It was already said that a model index does not and will not store data directly. It references data that's someplace else, that is - somewhere you've put it. It has 2 constructors to facilitate that:
- one that takes a
void *
- a generic pointer to something - one that takes an integer - a generic index to something
It is your responsibility to keep and manage the data.
- one that takes a
-
@kshegunov said in Subclassing QModelIndex - private constructor?:
@Dariusz said in Subclassing QModelIndex - private constructor?:
@Christian-Ehrlicher It stores a pointer to data node
First of all, it stores an opaque pointer, which can be any pointer.
Except it cant store shared_ptr ?
I'm trying to store the same thing but my objects are done via shared_ptr instead of raw pointers.
Secondly, this is not a pointer! This is an object that aggregates a pointer. An object, no matter what it contains, isn't a pointer itself.
Hmm yeap true. Still it has "pointer" written all over it and as far as I can tell its raw 2.0 pointer. Even Qt has its own implementation of QSharedPtr as far as I remember. Perhaps they all should change the naming to call it shared_wrapper/smart_wrapper ? / anyway waving off the topic here.
So again, I kinda need to extend the class or else a way to pass shared_ptr to the void*adata parameter/quintptr.
You can't and you will not. If you want to reference a list of shared pointers, put them in a vector, and store the index of the element inside the model index. When you need to get the shared pointer, take the index of the element from the model index and get the shared pointer from the vector.
Not sure how much performance that will yeld, I'm looking at milions of objects, if I need to keep making/deleting vectors I will lose cycles on just handling the massive vector list. Not to mention if I want to delete 500k objects, then I need to filter over the vector to clear objects there too... with shared_ptr/QModelIndex, the second QModelIndex dies and if its the last index then the object would get deleted too.
@kshegunov Is that not good enough reason to expose the constructor to allow users to subclass the QModelIdnex class to allow for a work around to store it?
No. It was already said that a model index does not and will not store data directly. It references data that's someplace else, that is - somewhere you've put it. It has 2 constructors to facilitate that:
- one that takes a
void *
- a generic pointer to something - one that takes an integer - a generic index to something
It is your responsibility to keep and manage the data.
It does not store data no, yes that's correct. But it stored a pointer to the data.
Right now QStandardModelItem/QStandardItem are based on *Raw pointers. So it's all nice. But if a user(me) wants to use QAbstractItemModel & customItem based on shared_ptr<> then I have no way of using QModelIndex to store/retrieve the internalPointer in a correct format that won't break shared_ptr<>.As far as I can tell shared_ptr are being pushed out there to replace raw ptrs so that memory leaks are easier to fix and memory is managed better. Why is it so hard to either expose constructor for qmodelIndex or add a way for it to work with shared_ptr? All its need is std::shared_ptr<void>> - but that needs more hassle, or just expose the constructor from private to public? :/
Sorry if I'm being a little "Stubborn" but we have the tools to replace qabstractmodel/treeView/item etc. But nothing for ModelIndex...
- one that takes a
-
@Dariusz said in Subclassing QModelIndex - private constructor?:
But it stored a pointer to the data.
No, it does not store anything, you're wrong. A QModelIndex has no ownership on something. A shared_ptr is exactly the opposite - it is a shared ownership to a data structure/object.
-
@Dariusz said in Subclassing QModelIndex - private constructor?:
Except it cant store shared_ptr ?
Because that's an object, not a pointer. It has additional data it holds, beside the pointer to your object. In fact it holds at the very least an integer and one pointer in addition to the original pointer to the object.
Hmm yeap true. Still it has "pointer" written all over it and as far as I can tell its raw 2.0 pointer.
No it is not. It's a rather expensive mechanism that allows to share ownership to a pointer. And just to be clear, it does not share ownership to the data a pointer references, only to the pointer.
Perhaps they all should change the naming to call it shared_wrapper/smart_wrapper ?
Take that with the standards committee. Sharing of pointers is quite the rare case anyway.
Not sure how much performance that will yeld, I'm looking at milions of objects, if I need to keep making/deleting vectors I will lose cycles on just handling the massive vector list.
Yeah, and atomic reference counting over an external counter is absolutely free, right?
Not to mention if I want to delete 500k objects, then I need to filter over the vector to clear objects there too... with shared_ptr/QModelIndex, the second QModelIndex dies and if its the last index then the object would get deleted too.
If you need to allocate/delete half a million objects the heap manager will eat up your CPU time like it never existed anyway.
new
/delete
ain't free of charge.But it stored a pointer to the data.
You can store a pointer to the data if you wish.
QModelIndex
will not take ownership, however, so even semantically giving it a shared pointer is wrong. You're trying to forceQModelIndex
to be owner of some pointer you share with other parts of your program. You're fighting with the model-view framework. I repeat, it is wrong and will not work.Right now QStandardModelItem/QStandardItem are based on *Raw pointers. So it's all nice. But if a user(me) wants to use QAbstractItemModel & customItem based on shared_ptr<> then I have no way of using QModelIndex to store/retrieve the internalPointer in a correct format that won't break shared_ptr<>.
Because you made a wrong design choice. You'll just have to live with it. I understand what you want to do, it's not going to happen.
As far as I can tell shared_ptr are being pushed out there to replace *raw ptrs so that memory leaks are easier to fix and memory is managed better.
You are wrong. If that were true you'd see everything in Qt passed through a shared pointer. Have you? Of course not, because external reference counting is not "memory management" by itself. Proper memory management requires discipline to declare clearly what object owns what memory, which many people lack or simply refuse to acknowledge. The
std::shared_ptr
and it's Qt conterpartQSharedPointer
are good for one thing and one thing alone - objects that manage their own lifetime, i.e. they are not owned by any other object, thus the reference to them must be shared.Why is it so hard to either expose constructor for qmodelIndex or add a way for it to work with shared_ptr?
Many reasons. One of them is it breaks binary compatibility. Another is that
QModelIndex
has to be a template (or an abstract) class to be able to do it, which isn't happening because it can't work with the rest of the model/view. And last, but not least, it's neither necessary, nor is it a correct approach.All its need is std::shared_ptr<void*>> - but that needs more hassle, or just expose the constructor from private to public? :/
QModelIndex
isn't made to be derived, that's why it has a private constructor. -
@kshegunov said in Subclassing QModelIndex - private constructor?:
If you need to allocate/delete half a million objects the heap manager will eat up your CPU time like it never existed anyway
And the whole ref-counting stuff will eat the last cycles when there are some left... :)