680c407b   
   From: daniel.kruegler@googlemail.com   
      
   Am 14.03.2012 22:31, schrieb Gene Bushuyev:   
   > On Mar 2, 1:42 pm, Daniel Krügler   
   > wrote:   
   >> On 2012-03-02 11:41, Gene Bushuyev wrote:   
   >>   
   >>> I was looking at the C++11 standard docs and didn't see iterators for   
   >>> rvalue containers.   
   > ...   
   >> The standard did not miss to add them. It would be possible to follow   
   >> your suggestion with the cost of   
   >>   
   >> a) replacing all container begin/end pairs by a double-pair each one   
   >> &-ref-qualified and&&-ref-qualified   
   >>   
   >> b) doubling the number of iterators with in each container:   
   >> &-ref-qualified begin/end functions return the normal one,   
   >> &&-ref-qualified returning a moving iterator instead.   
   >>   
   >> Instead the standard chose a more economic and useful feature:   
   >> std::move_iterator. Just replace your code above by   
   >>   
   >> MyContainer::MyContainer(vector&& v)   
   >> {   
   >> reserve(v.size());   
   >> uninitialized_copy(std::make_move_iterator(v.begin()),   
   >> std::make_move_iterator(v.end()), data);   
   >> size = v.size();   
   >>   
   >> }   
   >   
   > Thank you for pointing move_iterator template to me, but it doesn't   
   > look like a better solution.   
      
   That depends on the weights used for the measure. make_move_iterator   
   solves the problem and *not* adding all these overloads plus one further   
   iterator type is much easier to learn or to teach. It is also much   
   easier to specifier. I consider all these arguments as relevant.   
      
   > I would rather see all containers having   
   > defined all functions:   
   >   
   > using iterator =   
   > using const_iterator =   
   > using move_iterator =   
   >   
   > iterator begin()& ;   
   > const_iterator begin() const&;   
   > move_iterator begin()&&;   
      
   As I said before, this would have considerably increased the number of   
   all iterator-returning functions and it would not make C++03 containers   
   move-aware via the iterator. Further, the story has not yet ended:   
   (r)(c)begin()/(r)(c)end() are not the only iterator-returning functions,   
   just look for all remaining iterator-returning functions in the string   
   clause or the container clause. In addition, any user-code that wants to   
   create a C++11 container has to create all the boiler-code to satisfy   
   the requirements. IMO two instead of three function for each such   
   iterator function is more than enough!   
      
   Please refer to some real arguments, because from what you write so far   
   I really cannot deduce the overall advantage of such a change.   
      
   > Because, it might be unknown, whether a container comes as an lvalue   
   > or rvalue, and thus one need a duck-typing way of addressing it, for   
   > example:   
   >   
   > template   
   > auto unique(V&& v) -> set remove_reference::type::value_type>   
   > {   
   > return set::type::value_type>   
   > (forward(v).begin(), forward(v).end());   
   > }   
      
   If this pattern occurs often for you, it could be useful to introduce   
   once and for all a helper function that maps rvalue containers to a   
   moving iterator range, else a normal iterator range. This is easy to   
   realize, e.g.   
      
   #include    
   #include    
   #include    
      
   template   
   inline auto make_iterator_range(C&& c) ->   
   typename std::enable_if::value,   
    std::pair   
   >::type   
   {   
    return {c.begin(), c.end()};   
   }   
      
   template   
   inline auto make_iterator_range(C&& c) ->   
   typename std::enable_if::value,   
    std::pair<   
    decltype(std::make_move_iterator(c.begin())),   
    decltype(std::make_move_iterator(c.end()))   
    >   
   >::type   
   {   
    return {std::make_move_iterator(c.begin()),   
   std::make_move_iterator(c.end())};   
   }   
      
   #include    
      
   int main() {   
    using C = std::vector;   
    C c1{};   
    auto r1 = make_iterator_range(c1);   
    static_assert(std::is_same>::value, "");   
    const C c2{};   
    auto r2 = make_iterator_range(c2);   
    static_assert(std::is_same>::value, "");   
    auto r3 = make_iterator_range(C{});   
    static_assert(std::is_same,   
   std::move_iterator>>::value, "");   
   }   
      
   This has no intrusive effects on the container specification.   
      
   I would like to point out that the last example is a typical mis-usage,   
   because the life-time of the C temporary has ended after the   
   construction of r3, but I added it anyway just to demonstrate that the   
   expected return type corresponds to the obtained one.   
      
   Now you can easily implement your suggested function like so:   
      
   template   
   auto unique(V&& v) -> set::type::value_type>   
   {   
    auto r = make_iterator_range(forward(v));   
    return set::type::value_type>   
    (r.first, r.second);   
   }   
      
   > The same way it would have been better if std::begin and std::end   
   > templates were using perfect forwarding, instead of const and non-   
   > const lvalue versions.   
      
   There is no fundamental reason why the standard could not be extended in   
   the future to realize that. You could write-up a proposal for this, for   
   example.   
      
   HTH & Greetings from Bremen,   
      
   Daniel Krügler   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)