On Thursday, 16 May 2019 08:26:08 PDT Mutz, Marc via Development wrote: > > That goes against the Qt API design. Do not return views, since it > > implies > > that internally there is an object that produces that view and that it > > does > > not go out of scope. The reason we return full, owning containers is so > > we > > have the freedom inside to change how we store the data without that > > affecting > > our API. > > I believe the opposite to be true: I believe owning container use in the > API to break a class' encapsulation: > > If you return QVector<>, which choices do you have for the internal data > structure? A QVector.
When you first design the class, sure. But 5 years later, you may have the data internally kept in a QMap or QHash, mapped to some other information. So your function that used to "return d->member;" now does "return d->member.keys();" Another case would be where you're keeping extra data in the internal structure and you need to filter that out before returning. Or the dual: augment with some implied data. The latter could be quite common if the class is not storing anything in the regular case, but synthesising it on demand for the benefit of the old API. > If you return a view, you can use a std::vector, a QVector, a C array > internally, even switch at runtime (like QRegion does for the case of a > single rect). So views allow the implementation to vary its internal > data storage strategy while returning owning containers does not. But only so long as each of those containers store lay the data out the same way in memory, which is not the case for my QMap example. > And no, you _can_ write views for node-based containers, too. Cf. how > QVariant is (indirectly) iterable these days. Sure, but you'd have to change the public API to return that view instead of the contiguous-storage one. Unless we predict that that would be the case and always return a view that uses an indirect data-access method, which potentially owns the data. Does such a view exist? > Sure, you'd not return a view to data that the class in question does > not already own, though with coroutines you could return a generator > instead. This is about the data that is already stored in the object. > This is about QRegion::rects() and QGradient::stops(). This is also > about QAIM::roleNames(). All these APIs lock down the implementation to > a particular data store, thus _reducing_ the implementation's freedom to > adjust it's internal workings. And by Hyrum's Law, they also make users > depend on idiosyncrasies of the implementation, as witnessed by the > pre-QRegion::begin/end() anti-pattern of abusing boundingRect() when > rectCount() == 1 in order to avoid the building of a QVector just to > store one rectangle, a special-casing I could remove in 100% of cases > once QRegion became iterable (= a view on it's rects property). Two of your examples basically return an internal structure, so I'm not seeing how they are relevant. QGradient::stops is a good example that synthesises data on-demand in one case: if (m_stops.isEmpty()) { QGradientStops tmp; tmp << QGradientStop(0, Qt::black) << QGradientStop(1, Qt::white); return tmp; } return m_stops; How would you implement this one with a view-based return? -- Thiago Macieira - thiago.macieira (AT) intel.com Software Architect - Intel System Software Products _______________________________________________ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development