With old-style loops, I can delve into a QJsonArray
and, in the example below, add element "foo" with contents of existing element "bar" for each array item. How can I do this using C++11 range-based for?
// QJsonArray oldArray contains an array of which one element is "bar"
QJsonArray newArray;
int i, b = oldArray.count();
for (i=0; i<n; ++i) {
QJsonObject element = oldArray.at(i).toObject();
element["foo"] = element["bar"];
newArray.append(element);
}
I have tried the following (admittedly as trial and error):
for (auto& element : oldArray) {
element["foo"] = element["bar];
newArray.append(element);
}
I get the error
non-const lvalue reference to type 'QJsonValueRef' cannot bind to a temporary of type 'QJsonValueRef'
for (const auto& element : oldArray) {
...
I get a warning
loop variable 'element' is always a copy because the range of type 'QJsonArray' does not return a reference
for (const auto element : oldArray) {
element["foo"] = element["bar];
...
I get the error
no viable overloaded operator[] for type 'const QJsonValueRef'
relating to element["bar"]
The problem is that the iterator for QJsonArray
returns a temporary QJsonValueRef
object, and lvalue references can not bind to temporaries. We can either hold that temporary by value:
// QJsonArray oldArray contains an array of which one element is "bar"
QJsonArray newArray;
for (auto v : oldArray) {
QJsonObject element = v.toObject();
element["foo"] = element["bar"];
newArray.append(element);
}
In this case v
is a QJsonValueRef
object (similar to what oldArray.at(i)
gives in the old-style loop). After that, we convert that QJsonValueRef
to a QJsonObject
using .toObject()
.
Or we can use forwarding references since they can bind to rvalues:
for (auto&& v : oldArray) {
...
}
In this case v
is deduced to be an rvalue reference to a QJsonValueRef
.
Both solutions are identical in terms of the number of objects being created/destructed (since in the former, the copy is elided under C++17 guaranteed copy elision rules or even in pre-C++17 when using any decent compiler. In the latter, the reference is bound to the temporary and this prolongs its lifetime to match the whole iteration).
std::vector<bool>
; since both std::vector<bool>
and QJsonArray
have iterators that return proxy objects.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With