QGIM: test if a tuple row is valid before dereferencing
Row types that are convertible to bool, such as pointers, but also unique_ptr and similar wrappers, should not be dereferenced when accessing values for reading or writing. This is already done implicitly when operating on single-value types, but for tuples we have to do so explicitly, before accessing the element. For example, inserting a row where the row type is a pointer will leave that row be nullptr in the range, and both data and setData should fail until a row has been constructed. For rows that are pointers to tuples, we must never call get<>, as get cannot test if the item received is a nullptr and still return a valid value (reference). Since e.g. unique_ptr is explicitly convertible to bool we have to use std::is_constructible rather than is_convertible, as the latter only works for types that are implicitly convertible. Change-Id: I9dbdf6e5cac0146ed5d1b88c523e182590b0c8ab Reviewed-by: Artem Dyomin <artem.dyomin@qt.io>
This commit is contained in:
parent
5be58ac927
commit
9f63577ddd
@ -277,7 +277,7 @@ public:
|
||||
readData(*std::next(std::cbegin(row), index.column()));
|
||||
else if constexpr (static_column_count == 0)
|
||||
readData(row);
|
||||
else
|
||||
else if (QGenericItemModelDetails::isValid(row))
|
||||
for_element_at(row, index.column(), readData);
|
||||
}
|
||||
return result;
|
||||
@ -328,7 +328,7 @@ public:
|
||||
success = writeData(*std::next(std::begin(row), index.column()));
|
||||
} else if constexpr (static_column_count == 0) {
|
||||
success = writeData(row);
|
||||
} else {
|
||||
} else if (QGenericItemModelDetails::isValid(row)) {
|
||||
for_element_at(row, index.column(), [&writeData, &success](auto &&target){
|
||||
using target_type = decltype(target);
|
||||
// we can only assign to an lvalue reference
|
||||
@ -361,7 +361,7 @@ public:
|
||||
} else if constexpr (static_column_count == 0) {
|
||||
row = row_type{};
|
||||
success = true;
|
||||
} else {
|
||||
} else if (QGenericItemModelDetails::isValid(row)) {
|
||||
for_element_at(row, index.column(), [&success](auto &&target){
|
||||
using target_type = decltype(target);
|
||||
if constexpr (std::is_lvalue_reference_v<target_type>
|
||||
|
@ -178,6 +178,15 @@ namespace QGenericItemModelDetails
|
||||
template <typename T> static auto pointerTo(T &t) { return std::addressof(t); }
|
||||
template <typename T> static auto pointerTo(const T &&t) = delete;
|
||||
|
||||
template <typename T>
|
||||
static bool isValid(T &&t)
|
||||
{
|
||||
if constexpr (std::is_constructible_v<bool, T>)
|
||||
return bool(t);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename It>
|
||||
auto key(It&& it) -> decltype(it.key()) { return it.key(); }
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user