[Qt-interest] QList<T> conversion
Thiago Macieira
thiago at kde.org
Tue Feb 1 23:43:29 CET 2011
On Tuesday, 1 de February de 2011 17:36:24 Guillaume CLEMENT wrote:
> Usually the problem is, what happens if the "doFoo" function adds an
> incompatible object to the list ? It can do so, since the list is a
> QList<QObject*>.
Right, this is a problem. That's why this is allowed in C++:
struct Base {};
struct Derived: Base { void someDerivedMethod(); };
Derived d;
Derived *d_ptr Base *b_ptr
but the following isn't:
Derived **d_ptr_ptr Base **b_ptr_ptr
Because if the above were allowed, you could do:
Base b;
Base *b_ptr b_ptr_ptr (*d_ptr_ptr)->someDerivedMethod();
> For example with this code :
>
>
> QList<A*> *firstList > QList<QObject*> *secondList >
> secondList ->append(new B()); // Wh
re B
> inherits QObject but not A
>
> A *a > What happens ? My guess is that A will be invalid and reading / writing to
> it would be bad at this stage.
>
>
>
> Some B was just added in firstList, although it is not a A. But firstList is
> a QList<A*>.
Right, your example would cause problems. It's introduced by the
reinterpret_cast.
But that's not what I had suggested. I never suggested keeping a different
QList pointer to the same list. I suggested making a copy but keeping the same
data:
QList<A *> firstList QList<QObject *> secondList *reinterpret_cast<QList<QObject *> *>(&firstList);
By the QList construction, the above works, even the implicit sharing. It
means that, just after my lines above, firstList and secondList share the same
data.
However, the moment that you do:
secondList << new B;
Then they no longer share the same bits. The original list still has only A
elements.
This concept is called Co-variance and Contra-variance (nothing to do with
QVariant). Read more at:
http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)
It also says:
> The operator which constructs array types from element types is usually
> covariant on the base type: since String ⤠Object then ArrayOf(String) â¤
> ArrayOf(Object). Note that this is only correct (i.e. type safe) if the
> array is immutable; if insert and remove operators are permitted, then
> the insert operator is covariant (e.g. one can insert a String into an
> ArrayOf(Object)) and the remove operator is contravariant (e.g. one can
> remove an Object from an ArrayOf(String)). Since the mutators have
> conflicting variance, mutable arrays should be invariant on the base
> type.
The C++ support for covariants and contravariants is incomplete. C++ supports
covariant returns in virtual overrides, but not contravariant arguments, since
arguments are used in overloading resolu
ion.
However, C++ doesn't technically need contravariant overriding. Given the two
types above:
struct BaseClass
{
virtual void doSomething(Derived *);
};
struct DerivedClass: public BaseClass
{
virtual void doSomething(Base *);
private:
virtual void doSomething(Derived *d)
#ifdef __GXX_EXPERIMENTAL_CXX0X__
final
#endif
;
};
--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Senior Product Manager - Nokia, Qt Development Frameworks
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 187 bytes
Desc: This is a digitally signed message part.
Url : http://lists.qt-project.org/pipermail/qt-interest-old/attachments/20110201/3391db9e/attachment.bin
More information about the Qt-interest-old
mailing list