Tech Off Post

Single Post Permalink

View Thread: (STL) move_if algorithm, what's your take on it ?
  • Jonas_No

    Making move_if support input iterators will make it become "partition_move" or did you have something else in mind ?

    With find_if  in move_if it'll be N+1, is that correct ?
    Since one item is tested twice. 

    #include <algorithm>
    #include <vector>
    #include <iostream>
    #include <iterator>
    #include <sstream>
    
    using namespace std;
    
    template <typename FwdIt, typename OutIt, typename Predicate>
    inline FwdIt move_if(FwdIt first, FwdIt last, OutIt out, Predicate pred)
    {
        first = find_if(first, last, pred);
    
        for (auto i = first; i != last; ++i)
        {
            if (pred(*i)) // Should it move it ?
                *out++ = move(*i); // Move it.
            else
                *first++ = move(*i);
        }
        return first;
    }
    
    // move_if have become partition_move
    template <typename InIt, typename OutIt1, typename OutIt2, typename Predicate>
    inline pair<OutIt1, OutIt2> move_if(InIt first, InIt last, OutIt1 out_false, OutIt2 out_true, Predicate pred)
    {
        for (auto i = first; i != last; ++i)
        {
            if (pred(*i)) // Should it move it ?
                *out_true++ = move(*i); // Move it.
            else
                *out_false++ = move(*i);
        }
        return make_pair<OutIt1, OutIt2>(out_false, out_true);
    }
    
    int main()
    {
        auto is_even = [](const char c){return (c % 2) == 0;};
    
        std::istringstream iss("The quick brown fox jumps over the lazy dog");
        std::istream_iterator<char> begi(iss), endi;
    
        vector<char> n_f, n_t;
        move_if(begi, endi, back_inserter(n_f), back_inserter(n_t), is_even);
    
        auto print_vec_char = [](const vector<char> &v) {
            cout << "[" << v.size() << "]";
            for_each(v.cbegin(), v.cend(), [](const char c) {
                cout << " " << c;
            });
            cout << endl;
        };
        
        print_vec_char(n_f);
        print_vec_char(n_t);
    }
    
    /* Output:
    [19] e q u i c k o w o u m s o e e a y o g
    [16] T h b r n f x j p v r t h l z d
    */
    

     

    > I was assuming that the whole source range would be discarded.

     How would you do it if the source range would be used ?

     

    I a pedant so making my code as efficient as possible is a goal.

    Using move_if is more efficient because you need one less container and if you really needed to preserve the input container then partition_copy would do the trick.