tags:

views:

862

answers:

4

Is there any specific reason for not having std::copy_if algorithm in C++ ? I know I can use std::remove_copy_if to achieve the required behavior. I think it is coming in C++0x, but a simple copy_if which takes a range, a output iterator and a functor would have been nice. Was it just simply missed out or is there some other reason behind it?

+5  A: 

Multiple sources indicate that it was left out of STL by accident.

However, I am not sure if that's a fact or a self-perpetuating myth. I'd appreciate if anyone would point out a source more credible than a link to a random post on the Internet.

Alex B
Here's a non-random post on the internet, selected on the basis that it claims to be an email from Stroustrup to the Boost mailing list: http://lists.boost.org/Archives/boost/2001/01/8030.php. Of course it could be a fraud, or it could be that Stroustrup himself has bought the myth. I guess it's possible that Stepanov generally thought it best to have `remove_copy_if`, and deliberately excluded `copy_if` as redundant. But seriously, it's clearly some kind of mistake to have `remove_copy_if` but not `copy_if`, if only one of taste :-)
Steve Jessop
+10  A: 

According to Stroustrup's "The C++ Programming Language" it was just an over-sight.

(as a citation, the same question answered in boost mail-lists: copy_if)

sbk
+4  A: 

Stroustrup says they forgot it.

However, you can use remove_copy_if (which really should be called copy_if_not) along with not1 instead.

rlbond
+4  A: 

It's dead easy to write your own:

template <class InputIterator, class OutputIterator, class Predicate>
OutputIterator copy_if(InputIterator first, InputIterator last,
                       OutputIterator result, Predicate pred)
{
  return std::remove_copy_if(first,last,result,std::not1(pred));
}

Edit: This version works with all predicates:

template <class InputIterator, class OutputIterator, class Predicate>
OutputIterator copy_if(InputIterator first, InputIterator last,
                       OutputIterator result, Predicate pred)
{
  while(first!=last)
  {
    if(pred(*first))
        result = *first;
    ++first;
  }
  return result;
}
alex tingle
This isn't actually correct, as noted in *Effective STL* item 36, because it only works on adaptable functors.
rlbond
looks like it's not that dead easy, it seems that your second attempt returns the first value matching the predicate - besides, IMHO, you're a little off-topic here
rotoglup
rotoglup - I'm afraid that you don't know what you're talking about. 'result' is an OutputIterator. I did test this code you know.
alex tingle
Don't you have to iterate the OutputIterator? `*(result++) = *first;`
Peter Kovacs
@Peter Kovacs - nope. I thought that too at first, but if you check you'll find that you don't need to explicitly increment it.
alex tingle
I think that might just be a side-effect of the way the stl output iterators work. For example this code fails to compile with your copy_if: `int A[] = { 1, 2, 3, 4, 5, 6 }, B[ 3 ];` `copy_if( A, A + sizeof( A ) / sizeof( A[ 0 ] ), B, `However, it works if you use `*result++ = *first;`
Peter Kovacs