Commit Graph

9 Commits (5ea248155654b58fcb52ef326dc4d94de83d0409)

Author SHA1 Message Date
Alexandru Croitor fb69efb9c9 CMake: Make a few more auto tests standalone
Pick-to: 6.7
Change-Id: I80988114bd906447a2ab712d5432a489e095a5c1
Reviewed-by: Joerg Bornemann <joerg.bornemann@qt.io>
2024-03-14 01:14:18 +01:00
Giuseppe D'Angelo 7f7b5ff3a1 QSpan: add construction from initializer_list
P2447 has been merged in C++26, backport the same functionality.

This makes QSpan<const T> a proper replacement for a const QList<T>&
parameter, because now both can be built via a braced-init-list.

  // void f(const QList<int> &l); // old
  void f(QSpan<const int>);       // new

  f({1, 2, 3});                   // now OK

This is, technically speaking, SiC: in the presence of both `f`
overloads, the code above would have called the QList one. Now instead
the call is ambiguous.

We've been there already -- this is QString and QStringView all over
again, and the solution is the same: get rid of the owning container
overload. I'd rather have this construction *sooner* rather than *later*
in order to minimize the fallout.

And just like QString vs QStringView, there's nothing really doable to
prevent instant-dangling situations:

  QStringView v = getString();    // dangles
  QSpan<const int> s = {1, 2, 3}; // ditto

except for using QSpan (QStringView) as a *parameter type only*.

Note that QSpan with dynamic extent was already convertible from
std::initializer_list through its ranged constructor. However this fact
alone doesn't unlock the above syntax. QSpan with a static extent was
also convertible for the same reason. (This is non-standard:
std::span's range constructor for static extents is explicit, but QSpan
doesn't follow that design choice and makes the constructors implicit
instead.)

Found in API-review.

Pick-to: 6.7
Change-Id: I160ab5b292b0c2568cd9a7ad1b4430085f475c29
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
2024-03-06 08:44:46 +00:00
Lucie Gérard ff1039c217 Change license for tests files
According to QUIP-18 [1], all tests file should be
LicenseRef-Qt-Commercial OR GPL-3.0-only

[1]: https://contribute.qt-project.org/quips/18

Pick-to: 6.7
Task-number: QTBUG-121787
Change-Id: I9657df5d660820e56c96d511ea49d321c54682e8
Reviewed-by: Christian Ehrlicher <ch.ehrlicher@gmx.de>
2024-02-04 09:56:42 +01:00
Marc Mutz 94e122c594 QSpan: make adl_begin() etc SFINAE-friendly
The definition of iterator_t, and, therefore, of is_compatible_range
depends on this, otherwise say, 0, is being treated as a valid range
and hits a hard error in adl_begin() when trying to call begin(int&).

TIL: decltype(auto) does _not_ SFINAE.

Fix by calculating the return type manually, re-enabing SFINAE.

Pick-to: 6.7 6.6
Change-Id: Icacd70554f4050ecaeb396c9ae60bc4f21a220c9
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
2024-01-26 23:50:57 +01:00
Marc Mutz 03e78e5d62 Long live QSpan as public API!
Provide qspan_p.h as backward-compatibility header.

[ChangeLog][QtCore][QSpan] New Qt equivalent of std::span.

Fixes: QTBUG-115022
Change-Id: I1cc27dc0aa1f7406f0a41d7a75f176cd7f858feb
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-12-07 22:38:15 +00:00
Marc Mutz 7f5b795f75 QSpan: ensure interoperability with std::span
We accepted QSpan as a NIH-type instead of waiting for C++20 and
std::span, because we said that there's no impedance mismatch between
the two, as they both implicitly convert into each other.

But we actually never checked that they do.

Fix this omission by adding constructors that treat std::span exactly
the same as QSpan itself, and adding the respective static_assert()s
to tst_QSpan to check that (within the constraints imposed by the
standard on std::span), they actually do convert into each other.

The only two problematic cases are that fixed-size std::span
constructors are explicit, so span is only constructible, not
convertible, from QSpan. Likewise, for an rvalue QSpan to be
acceptable to the std::span constructor, QSpan needs to opt-in to
enable_borrowed_range (while we're at it, do enable_view, too).

We so far have rejected adding these opt-ins for our own container
classes because we wanted to avoid the compile-time overhead of
including the huge <ranges> header into such central headers as those
that define our containers.

But std::span itself has to specialize these traits, and its range
contructor has to use them, so they must be available from <span>,
too, possibly the stdlib puts the definition into a much smaller
header. So just assume we can specialize it after including just
<span>, provided __cpp_lib_concepts is also defined.

Pick-to: 6.6
Change-Id: I2202869b60c98047256b0fbcb12336f5d8e550ba
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-12-07 02:46:22 +01:00
Marc Mutz c851fb2456 QSpan: check conversion from initializer_list
The docs at cppreference.com hint at a corresponding ctor being added
for C++26 (though I don't see it in eel.is/c++draft, yet).

Even so, replacing former initializer_list functions with QSpan ones
is definitely one of the upcoming use-cases, so test it.

Can't use from_container_impl() here as initializer_list<T> is already
immutable, so QSpan<int> is not compatible, only QSpan<const int>.

Pick-to: 6.6
Change-Id: Iecdf29e629d48313edd5e56d358b9137da76deb6
Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-12-07 02:46:13 +01:00
Marc Mutz 368ea559eb QSpan: add C++23 c{,r}{begin,end}()
It was weird that they were missing. Now that C++23 added them to
std::span, add them to QSpan, too.

Pick-to: 6.6
Change-Id: I4a9b1fdeda66bc7b133c8f7b3b269656e5faffa3
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
2023-10-12 21:38:54 +02:00
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