In GitHub repositories there are not few examples where the range-expression in range-based for loop is surrounded in std::move, e.g. in pytorch:
...
outputs = (*call_op)(schema, std::move(inputs), std::move(outputs));
for (auto&& output : std::move(outputs)) {
   torch::jit::push(*stack, std::move(output));
}
Since output here just iterates over the elements of std::move(outputs) and we have std::move(output) inside loop body, does for-loop is really different from the variant without the first std::move:
for (auto&& output : outputs) {
   torch::jit::push(*stack, std::move(output));
}
and if yes, can the difference be observed with some classes from the standard library or only with some specially designed ones?
The range-based for statement is defined by translation:
{
   init-statement_opt
   auto &&range = for-range-initializer ;
   auto begin = begin-expr ;
   auto end = end-expr ;
   for ( ; begin != end; ++begin ) {
      for-range-declaration = * begin ;
      statement
   }
}
where begin-expr and end-expr either are range.begin() and range.end(), or are begin(range) and end(range), dependent on whether lookup for the former succeeds.
This means that within begin-expr and end-expr, range is an lvalue, regardless of whether for-range-initializer is an lvalue or an xvalue (or even a prvalue).
So wrapping a for-range-initializer in std::move() will not have any effect on program behavior.
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