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?
-
4It will be added to the next standard. The current draft has it under chapter 25.2.1 in the algorithms library. – David Rodríguez - dribeas Sep 19 '09 at 16:54
-
Duplicate: http://stackoverflow.com/questions/794320/are-they-adding-copyif-to-c0x – j_random_hacker Sep 20 '09 at 16:52
6 Answers
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)

- 9,212
- 4
- 32
- 40
-
10As an update, the C++11 standard has corrected this oversight by adding a new `copy_if` algorithm: http://en.cppreference.com/w/cpp/algorithm/copy – Bret Kuhns Sep 23 '12 at 16:46
-
Is there a variant that passes the iterator to the the unary predicate instead of passing the result of dereferencing the iterator? I don't see one, but that seems like another oversight. – Levi Morrison Oct 08 '18 at 00:24
Stroustrup says they forgot it. It's in C++11.
However, you can use remove_copy_if
(which really should be called copy_if_not
) along with not1
instead.

- 65,341
- 56
- 178
- 228
-
7In my mind I always translate "remove_copy_if" to "copy_except" :) – StackedCrooked Apr 28 '11 at 22:03
-
1...as long as you're willing to accept that std::not1 is not compatible with a function pointer. (As I see has been discussed below...) – Michael Cornelius Feb 18 '13 at 20:32
Just for completeness, in case someone googles his/her way to this question, it should be mentioned that now (post C++11) there is a copy if algorithm. It behaves as expected (copies the elements in a range, for which some predicate returns true, to another range).
A typical use case would be
std::vector<int> foo{ 25, 15, 5, -5, -15 };
std::vector<int> bar;
// copy only positive numbers:
auto it = std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar),
[](int i){return !(i<0);
});

- 29,616
- 15
- 87
- 153
-
4Here'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 Apr 17 '10 at 02:45
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;
}

- 6,920
- 3
- 25
- 29
-
2This isn't actually correct, as noted in *Effective STL* item 36, because it only works on adaptable functors. – rlbond Sep 19 '09 at 18:00
-
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 Sep 26 '09 at 10:08
-
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 Sep 26 '09 at 10:14
-
4Don't you have to iterate the OutputIterator? `*(result++) = *first;` – Peter Kovacs Jan 26 '10 at 02:03
-
@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 Jan 27 '10 at 15:43
-
1-1: If `result` is an `OutputIterator` then why do you assign `*first` to it? Your code is wrong and @Peter Kovacs is correct. – Troubadour Apr 28 '11 at 22:28
-
3@Peter & Troubadour - of course you are both correct. Mea culpa. The code I wrote did actually work, but presumably that was only because of some crazy intersection between the implementation details and my test code. I have corrected it and +1'd you. – alex tingle May 03 '11 at 19:53
Just for completeness I will add that boost has boost::algorithm::copy_if
for those of you who cannot use c++11's version (like me) in boost/algorithm/cxx11/copy_if.hpp
which will use std::copy_if
when:
#if __cplusplus >= 201103L
// Use the C++11 versions of copy_if if it is available
using std::copy_if; // Section 25.3.1
#else
Example:
#include <boost/algorithm/cxx11/copy_if.hpp>
#include <boost/assign/list_of.hpp> // for 'list_of()'
#include <boost/foreach.hpp>
#include <iostream>
#include <vector>
#include <iterator>
struct Odd
{
bool operator()(int n)
{
return n & 1;
}
};
int main()
{
std::vector<int> v = boost::assign::list_of(0)(1)(2)(3)(4);
BOOST_FOREACH(int i, v)
std::cout << i << ' ' ;
std::vector<int> out;
boost::algorithm::copy_if(v.begin(), v.end(), std::back_inserter(out), Odd());
std::cout << std::endl;
BOOST_FOREACH(int i, out)
std::cout << i << ' ' ;
}
Output:
0 1 2 3 4
1 3

- 22,602
- 44
- 128
- 244