summaryrefslogtreecommitdiffstats
path: root/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
diff options
context:
space:
mode:
authorGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2025-04-16 11:59:36 +0200
committerGiuseppe D'Angelo <giuseppe.dangelo@kdab.com>2025-04-22 22:07:36 +0200
commitaca7fd4ee764747bfa168f3e0f184babd3875b49 (patch)
tree124098b6588c830024959555a94c1b99bf610d9d /src/plugins/sqldrivers/mysql/qsql_mysql.cpp
parent3a1f4f718d96bd6b08f261cdbc0736ba4f219193 (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