diff options
| author | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2025-04-16 11:59:36 +0200 |
|---|---|---|
| committer | Giuseppe D'Angelo <giuseppe.dangelo@kdab.com> | 2025-04-22 22:07:36 +0200 |
| commit | aca7fd4ee764747bfa168f3e0f184babd3875b49 (patch) | |
| tree | 124098b6588c830024959555a94c1b99bf610d9d /src/plugins/sqldrivers/mysql/qsql_mysql.cpp | |
| parent | 3a1f4f718d96bd6b08f261cdbc0736ba4f219193 (diff) | |
QKeyValueRange: make sure it is a viewable range
QMap/QHash::asKeyValueRange() returns a QKeyValueRange, which is a
range, but in some cases it doesn't satisfy viewable_range:
https://eel.is/c++draft/range.refinements#6
This causes reasonable code to fail to compile:
map.asKeyValueRange() | std::views::transform(...)
The reason for this is that, when called on a lvalue map,
asKeyValueRange() returns QKeyValueRange<Map<...> &>. This isn't a
viewable range: it's not a view itself, it's not a lvalue reference to
range, and it's not movable.
The last bit is actually a mistake, because QKeyValueRange<Map<...> &>
contains a reference, and thus it's not assignable. Fix it by making it
contain a pointer instead.
In principle this has ABI implications because we're making the type POD
(from non-POD), and this would allow usage of the tail padding on
Itanium. I am 100% sure that no-one is inheriting from QKeyValueRange.
We can also go a step further and decide to make QKeyValueRange a range
*view*, because it is -- it satisfies all the semantic concepts.
To elaborate, there are two different QKeyValueRange implementations,
one for lvalue maps (stores a pointer to the map) and one for rvalue
maps (moves the map into the range). Conceptually, they map to ref_view
and owning_view in the standard library.
For now I'm only making the QKeyValueRange<&> specialization for lvalue
maps a view. The other one in principle may satisfy the range view
requirements (as the containers are COW, so copy is actually O(1)) but
this is more questionable. A possibility would be to make it move-only,
but that's an API break.
To make QKeyValueRange<&> a view I'm inheriting from view_base, which an
empty class and thus doesn't affect ABI. (I'm not inheriting from
view_interface in order to avoid changing the API between the two cases
above.)
This work unveiled two problems in the implementation of QKeyValueRange.
The first was that the the deduction guides were actually unused for the
const-lvalue argument. This is because user-defined deduction guides
are added on top of the ones implictly generated by the compiler. The
primary template constructor was used to synthesize a deduction guide
that deduced a non-reference qualified T; the result was that a const
lvalue map would yield a mutable range over a copy of the map (!).
Fix this by getting rid of the deduction guides and explictly specifying
the template arguments of QKeyValueRange.
This fix in turn adds a problem for const rvalue maps (unlikely). The
idea in this case would be to move the map into the QKeyValueRange: the
range stores a map object, initialized by moving the source map.
For a const map source, the stored map should be const as well. But that
makes the range not movable (this is the point of things like
movable-box in the std), and therefore not a view. Since this is a
fringe case, I'm dropping the const for the inner stored map, so one can
effectively realize a mutating iteration over a const rvalue source map.
Task-number: QTBUG-105465
Change-Id: I70161029799376fd369e0332461a8a50e6062892
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'src/plugins/sqldrivers/mysql/qsql_mysql.cpp')
0 files changed, 0 insertions, 0 deletions
