 <p>Since your function is going to return a vector, you will have to make a new vector (i.e. copy elements) in any case. In which case, <code>std::remove_copy_if</code> is fine, but you should use it correctly:</p> <pre><code>#include &lt;iostream&gt; #include &lt;vector&gt; #include &lt;set&gt; #include &lt;iterator&gt; #include &lt;algorithm&gt; #include &lt;functional&gt; std::vector&lt;int&gt; filter(const std::vector&lt;int&gt;&amp; all, const std::set&lt;int&gt;&amp; bad) { std::vector&lt;int&gt; result; remove_copy_if(all.begin(), all.end(), back_inserter(result), [&amp;bad](int i){return bad.count(i)==1;}); return result; } int main() { std::vector&lt;int&gt; all_items = {4,5,2,3,4,8,7,56,4,2,2,2,3}; std::set&lt;int&gt; bad_items = {2,8,4}; std::vector&lt;int&gt; filtered_items = filter(all_items, bad_items); copy(filtered_items.begin(), filtered_items.end(), std::ostream_iterator&lt;int&gt;(std::cout, " ")); std::cout &lt;&lt; std::endl; } </code></pre> <p>To do this in C++98, I guess you could use <code>mem_fun_ref</code> and <code>bind1st</code> to turn set::count into a functor in-line, but there are issues with that (which resulted in deprecation of bind1st in C++0x) which means depending on your compiler, you might end up using std::tr1::bind anyway:</p> <pre><code>remove_copy_if(all.begin(), all.end(), back_inserter(result), bind(&amp;std::set&lt;int&gt;::count, bad, std::tr1::placeholders::_1)); // or std::placeholders in C++0x </code></pre> <p>and in any case, an explicit function object would be more readable, I think:</p> <pre><code>struct IsMemberOf { const std::set&lt;int&gt;&amp; bad; IsMemberOf(const std::set&lt;int&gt;&amp; b) : bad(b) {} bool operator()(int i) const { return bad.count(i)==1;} }; std::vector&lt;int&gt; filter(const std::vector&lt;int&gt;&amp; all, const std::set&lt;int&gt;&amp; bad) { std::vector&lt;int&gt; result; remove_copy_if(all.begin(), all.end(), back_inserter(result), IsMemberOf(bad)); return result; } </code></pre>