title: Moving in range-based loop in generic C++ code?
body: <p>Imagine that you have this generic pseudo-code:</p>
  
  <pre><code>template&lt;typename Iterable&gt;
  void f(Iterable&amp;&amp; iterable)
  {
     ...
  }
  </code></pre>
  
  <p>We want to handle rvalue and lvalue references to iterable objects<sup>1</sup>, and the idea is that the function handles the container performing operations element by element.</p>
  
  <p>It is plausible that we want to forward the reference specification of the container to the elements. In other words, if <code>iterable</code> is an rvalue reference, the function will have to <em>move</em> the elements from the container.</p>
  
  <p>Using C++17, I would do</p>
  
  <pre><code>auto [begin, end] = [&amp;] {
      if constexpr(std::is_lvalue_reference_v&lt;Iterable&gt;)
          return std::array{std::begin(iterable),
                            std::end(iterable)};
      else
          return std::array{
              std::make_move_iterator(std::begin(iterable)),
              std::make_move_iterator(std::end(iterable))};
  }();
  std::for_each(begin, end, [&amp;](auto&amp;&amp; element)
  {
      ...
  });
  </code></pre>
  
  <p>Obviously, this is not the best code to maintain<sup>2</sup>, error prone and probably not so easy to optimize for the compiler.</p>
  
  <p>My question is: it could be possible, for future C++ standards, to introduce the concept of <em>forwarding range-based loops</em>? It would be nice if this</p>
  
  <pre><code>for(auto&amp;&amp; el : std::move(iterable))
  {
      ...
  }
  </code></pre>
  
  <p>could handle <em>el</em> as rvalue reference. In this way, this would be possible:</p>
  
  <pre><code>template&lt;typename Iterable&gt;
  void f(Iterable&amp;&amp; iterable)
  {
      for(auto&amp;&amp; el : std::forward&lt;Iterable&gt;(iterable))
      {
          /*
           *  el is forwarded as lvalue reference if Iterable is lvalue reference,
           *  as rvalue reference if Iterable is rvalue reference
           */
          external_fun(std::forward&lt;decltype(el)&gt;(el));
      }
  }
  </code></pre>
  
  <p>I am concerned about code-breaking changes, but at the same time I am not able to think about situations in which passing a rvalue reference as <em>argument</em> of a range based loop is expected to work without moving objects.</p>
  
  <p>As suggested, I tried to write down how I would change the 6.5.4 section of the standard. The draft can be read <a href="https://docs.google.com/document/d/1XiIPOcH3HBmICeUyQ4fHrDNfUpKha7znHYaid4Vomek/edit?usp=sharing" rel="nofollow noreferrer">at this address</a>.</p>
  
  <p>Do you think that it would be possible to introduce this feature without introducing serious issues?</p>
  
  <p><sub><sup>1</sup>Checked with C++20 concepts or static_asserts</sub><br/>
  <sub><sup>2</sup>And it's quite worse without C++17</sub></p>