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.