[Development] QList

Thiago Macieira thiago.macieira at intel.com
Thu Mar 23 21:16:55 CET 2017


On quinta-feira, 23 de março de 2017 12:41:56 PDT Marc Mutz wrote:
> On 2017-03-23 19:27, Thiago Macieira wrote:
> > In the mean time: why do you care if some class derives from
> > QStringView?
> 
> Because it's _wrong_.
> 
> It does not model is-a, so public inheritance is out of the question.

I beg to differ. It *is* "is-a": any modifiable QString is also a view to 
itself.

Also, remember the point that it would be a private base, so the is-a 
relationship is not visible. This is about code reuse, not about the semantic.

> QString cannot use a lot of QStringView functions (like mid()) without
> changing at least the return type, so inherit-to-reuse-implementation is
> also not valid.

For some cases, that's true, but only because functions like mid() try to 
return *this if they detect that there's no change. That's an optimisation 
inside QString, not a requirement of the interface.

A naïve implementation of QString::mid() could be:

QString QString::mid(int start, int len) const
{
	return QString(QStringView::mid(start, len));
}

> Last, there are no virtual functions in QStringView that QString would
> want to reimplement.

Virtual has nothing to do with anything. QString is complementing QStringView, 
only adding functionality.

> So, of the three use-cases for inheritance, none are relevant here, so
> it follows that inheritance is not the tool to use. You may consider
> composition, though, as I said, I'd rather provide free functions that
> most QString/View methods forward to than picking one class and calling
> its methods from all others.

From a strict theoretical point of view, that might be better.

From the practical point of view, implementing something as simple as

int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
	return QStringView(*this).indexOf(c, from, cs);
}

means:
1) we have an extra entry point in the library
2) so more symbols in the symbol table, increasing the chances of hash 
   collision
3) more code that, at best, inlines QStringView::indexOf into the new   
  function. That is, the best we can hope for is that the compiler turns the 
  above into:

int QString::indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
{
    return findChar(unicode(), length(), ch, from, cs);
}

Also note we'd probably want to mark findChar as Q_NEVER_INLINE so that the 
compiler doesn't expand the same function twice, which would mean an even 
bigger QtCore.

> > We certainly need to discuss the presence of an extra pointer inside,
> > as that
> > has a cost. But derivation?
> 
> Derivation is the strongest coupling mechanism in C++, after friendship.
> Do I need to mention QPolygon and what pain it's inheritance from
> QVector<QPoint> has caused? (FTR: cf. end of qvector.h and
> qvector_msvc.cpp).

Because MSVC ABI, like the Windows ABI, has severe shortcomings and actually 
violate the C and C++ standards. Some of them are legacy reasons from the 
1980s, like the one causing crashes reported in QTBUG-38876 (attempt for Qt 6 
fix at https://codereview.qt-project.org/189193 ).

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center




More information about the Development mailing list