template <class T, class A, class Predicate>
void erase_if(vector<T, A>& c, Predicate pred);
template <class T, class A, class Predicate>
typename vector<T, A>::size_type erase_if(vector<T, A>& c, Predicate pred);
Therefore, I think the erase_if function should return the number of elements that were erased. It can be declared astemplate <class T, class A, class Predicate>
typename vector<T, A>::size_type erase_if(vector<T, A>& c, Predicate pred);
Making it a non-member allows you to use type tags to implement it, instead of re-implementing it for every container, so you really only need to specialize for 1) containers that support erase(remove_if()) 2) list/forward list 3) associative containers
I don't really care if it returns the # removed, but having implemented this years ago in my own code base, I found 40 cases where I had used it, and I don't recall ever wanting the # removed.
If the predicate is supposed to do any processing then I think the right
return value might be the predicate, similarly to for_each.
This should also work well together with the proxy support from N4035.
If the result is discarded, the compiler will be able to elide its computation after inlining.
I'm curious, is there any general policy in the library on changing or not changing "return void" to something in any way useful?
Because assuming the statementIf the result is discarded, the compiler will be able to elide its computation after inlining.is true, a lot of member functions, for example, could potentially benefit from returning *this instead of void, but they still return void for some reason.
I suspect the benefit here isn't optimization, but rather code writing,
e.g. to be able to write:
std::vector<int> v;
v.clear().push_back(2).insert(v.begin(), 1); // etc.
(Not the best example, but hopefully you get the idea.)
On 2014-05-27 22:54, jgot...@gmail.com wrote:On Tuesday, May 27, 2014 12:44:50 PM UTC-4, Matthew Woehlke wrote:I suspect the benefit here isn't optimization, but rather code writing,
e.g. to be able to write:
std::vector<int> v;
v.clear().push_back(2).insert(v.begin(), 1); // etc.
(Not the best example, but hopefully you get the idea.)
I get the idea, and this example accidentally shows why this is not a good
idea. The v.begin() passed to the insert() function might be the value of
begin() at the beginning of the statement. If the push_back() allocated
memory (i.e. if v started with capacity() == 0), then that iterator will
be invalidated before the insert can be done, resulting in undefined
behavior.
(Getting way OT...) If that's actually possible I'd be inclined to call
it a bug in the language.
I'm having a hard time imagining under what
circumstances it's desirable to evaluate the arguments for a method
invocation before you are able to know what object the method will be
invoked against.