Commit Graph

1 Commits

Author SHA1 Message Date
Marc Mutz
f82cf6333e Long live QSpan!
QSpan is Qt's version of std::span. While we usually try not to
reimplement std functionality anymore, the situation is different with
QSpan. Spans are non-owning containers, so the usual impedance
mismatch between owning STL and Qt containers doesn't apply here:
QSpan implicitly converts to std::span and vice versa, making STL and
Qt APIs using spans completely interoperable.

We add QSpan mainly for two reasons: First, we don't want to wait
until we require C++20 in Qt and can use std::span. Second, in the
view of this author, some design decisions in std::span hurt the
primary use-case of spans: type-erasure for containers. This results
in two major deviations of QSpan from std::span: First, any rvalue
container is convertible to QSpan, allowing seamless passing of owning
containers to functions taking spans:

    void sspan(std::span<T>);
    void qspan(QSpan<T>);

    std::vector<T> v();
    sspan(v()); // ERROR: rvalue owning container
    auto tmp = v();
    sspan(tmp); // OK, lvalue
    qspan(v()); // OK

This author believes that it's more helpful to have compilers and
static checkers warn about a particular wrong usage than to make
perfectly valid use-cases impossible or needlessly verbose to code.

The second deviation from std::span is that fixed-size span
constructors are also implicit. This isn't as clear-cut, because an
explicit QSpan{arg} isn't per-se bad. However, it means you can't
transparently change from a function taking decltype(arg) to one
taking QSpan and back. Since that's exactly what we intend to do in Qt
going forward, in the interest of source-compatibility, the ctors are
all implicit.

Otherwise, the API of QSpan follows the std::span API very
closely. Like std::span, QSpan isn't equality_comparable, because it's
not clear what equality means for spans (element-wise equal, or (ptr,
size)-wise equal?). The major API additions are Qt-ish versions of std
API functions: isEmpty() on top of empty() and sliced() instead of
subspan(). The (nullary) first()/last() functions (Qt speak for
front()/back()) clash with the std::span function templates of the
same name, so are not provided.

This patch adds QSpan as private API. We intend to make it public API
in the future.

Pick-to: 6.6
Fixes: QTBUG-108124
Change-Id: I3f660be90eb408b9e66ff9eacf5da4cba17212a6
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Dennis Oberst <dennis.oberst@qt.io>
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
2023-07-21 17:00:05 +00:00