While using std::for_each algorithm how do I break when a certain condition is satisfied?
You can use std::any_of (or std::all_of or std::none_of) e.g. like this:
std::vector<int> a;
// ...
std::all_of(a.begin(), a.end(), [&](int val) {
// return false if you want to break, true otherwise
});
However, this is a wasteful solution (return values are not really used for anything), and you're better off writing you own loop.
You can use std::find_if algorithm, which will stop and return the iterator to the first element where the predicate condition applied to returns true. So your predicate should be changed to return a boolean as the continue/break condition.
However, this is a hack, so you can use the algorithms.
Another way is to use BOOST_FOREACH.
You can break from the for_each() by throwing an exception from your functor. This is often not a good idea however, and there are alternatives.
You can retain state in your functor. If you detect the 'break' condition, simply set a flag in your functor and then for each subsequent iteration simply return without doing your functor's thing. Obviously this won't stop the iteration, which might be expensive for large collections, but it will at least stop the work from being performed.
If your collection is sorted, you can find() the element that you want to break at, then do for_each from begin() to the element find() returned.
Finally, you can implement a for_each_if(). This will again not stop the iteration but will not evaluate your functor which does the work if the predicate evaluates to false. Here are 2 flavors of for_each_xxx(), one which takes a value and performs the work if operator==() evaluates to true, and another which takes two functors; one which performs a comparison ala find_if(), and the other which performs the work if the comparison operator evaluates to true.
/* ---
For each
25.1.1
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f)
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f)
Requires:
T is of type EqualityComparable (20.1.1)
Effects:
Applies f to each dereferenced iterator i in the range [first, last) where one of the following conditions hold:
1: *i == value
2: pred(*i) != false
Returns:
f
Complexity:
At most last - first applications of f
--- */
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first,
InputIterator last,
Predicate pred,
Function f)
{
for( ; first != last; ++first)
{
if( pred(*first) )
f(*first);
}
return f;
};
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first,
InputIterator last,
const T& value,
Function f)
{
for( ; first != last; ++first)
{
if( *first == value )
f(*first);
}
return f;
};
If you want do some actions while condition is not satisfied, maybe you need change algorithm on something like std::find_if?
As already shown by others it is only achievable with workarounds that IMHO obfuscate the code.
So my suggestions is to change the for_each into a regular for loop. This will make it more visible to others that you are using break (and maybe even continue).
You can't do it, unless you throw an exception, which is not a good idea because you don't do flow control with exceptions.
Update: apparently Boost has a for_each_if that might help, but you're not using Boost.
You throw an exception. Whether or not it's a good idea is sort of a style question, pace #Dan, but may be more of an issue with your design. for_each is intended for a sort of functional-programming style, which implicitly assumes that your function can be applied uniformly across the set. So, if you do need to break, that could be consiered an unusual condition, and therefore worthy of an exception.
The other solution, and a more "functional" solution, is to write your function so that if it shouldn't have an effect on some applications, then write it to have no effect. So, for example, if you had a summing function, have it add 0 in the cases you would have "broken" from.
You can use std::find_if instead std::for_each:
int aaa[]{ 1, 2, 3, 4, 5, 6, 7, 8 };
std::find_if(aaa, std::next(aaa, sizeof(aaa) / sizeof(int)), [](const auto &i) {
if (i == 5)
return true;
std::cout << i << std::endl;
return false;
});
Output:
1
2
3
4
Related
According to draft N4431, the function std::binary_search in the algorithms library returns a bool, [binary.search]:
template<class ForwardIterator, class T>
bool binary_search(ForwardIterator first, ForwardIterator last,
const T& value);
template<class ForwardIterator, class T, class Compare>
bool binary_search(ForwardIterator first, ForwardIterator last,
const T& value, Compare comp);
Requires: The elements e of [first,last) are partitioned with respect to the expressions e < value and !(value < e) or comp(e, value) and !comp(value, e). Also, for all elements e of [first,last), e < value implies !(value < e) or comp(e, value) implies !comp(value, e).
Returns: true if there is an iterator i in the range [first,last) that satisfies the corresponding conditions:
!(*i < value) && !(value < *i) or comp(*i, value) == false && comp(value, *i) ==
false.
Complexity: At most log2(last - first) + O(1) comparisons.
Does anyone know why this is the case?
Most other generic algorithms either return an iterator to the element or an iterator that is equivalent to the iterator denoting the end of the sequence of elements (i.e., one after the last element to be considered in the sequence), which is what I would have expected.
The name of this function in 1994 version of STL was isMember. I think you'd agree that a function with that name should return bool
http://www.stepanovpapers.com/Stepanov-The_Standard_Template_Library-1994.pdf
It's split into multiple different functions in C++, as for the reasoning it's nearly impossible to tell why someone made something one way or another. binary_search will tell you if such an element exists. If you need to know the location of them use lower_bound and upper_bound which will give the begin/end iterator respectively. There's also equal_range that gives you both the begin and end at once.
Since others seem to think that it's obvious why it was created that way I'll argue my points why it's hard/impossible to answer if you aren't Alexander Stepanov or someone who worked with him.
Sadly the SGI STL FAQ doesn't mention binary_search at all. It explains reasoning for list<>::size being linear time or pop returning void. It doesn't seem like they deemed binary_search special enough to document it.
Let's look at the possible performance improvement mentioned by #user2899162:
You can find the original implementation of the SGI STL algorithm binary_search here. Looking at it one can pretty much simplify it (we all know how awful the internal names in the standard library are) to:
template <class ForwardIter, class V>
bool binary_search(ForwardIter first, ForwardIter last, const V& value) {
ForwardIter it = lower_bound(first, last, value);
return it != last && !(value < *it);
}
As you can see it was implemented in terms of lower_bound and got the same exact performance. If they really wanted it to take advantage of possible performance improvements they wouldn't have implemented it in terms of the slower one, so it doesn't seem like that was the reason they did it that way.
Now let's look at it simply being a convenience function
It being simply a convenience function seems more likely, but looking through the STL you'll find numerous other algorithms where this could have been possible. Looking at the above implementation you'll see that it's only trivially more to do than a std::find(begin, end, value) != end; yet we have to write that all the time and don't have a convenience function that returns a bool. Why exactly here and not all the other algorithms too? It's not really obvious and can't simply be explained.
In conclusion I find it far from obvious and don't really know if I could confidently and honestly answer it.
The binary search algorithm relies on strict weak ordering. Meaning that the elements are supposed to be partitioned according to the operator < or according to a custom comparator that has the same guarantees. This means that there isn't necessarily only one element that could be found for a given query. Thus you need the lower_bound, upper_bound and equal_range functions to retrieve iterators.
The standard library contains variants of binary search algorithm that return iterators. They are called std::lower_bound and std::upper_bound. I think the rationale behind std::binary_search returning bool is that it wouldn't be clear what iterator to return in case of equivalent elements, while in case of std::lower_bound and std::upper_bound it is clear.
There might have been performance considerations as well, because in theory std::binary_search could be implemented to perform better in case of multiple equivalent elements and certain types. However, at least one popular implementation of the standard library (libstdc++) implements std::binary_search using std::lower_bound and, moreover, they have the same theoretical complexity.
If you want to get an iterator on a value, you can use std::equal_range which will return 2 iterators, one on the lower bound and one on the higher bound of the range of values that are equal to the one you're looking for.
Since the only requirement is that values are sorted and not unique, there's is no simple "find" that would return an iterator on the one element you're looking for. If there's only one element equal to the value you're looking for, there will only be a difference of 1 between the two iterators.
Here's a C++20 binary-seach alternative that returns an iterator:
template<typename RandomIt, typename T, typename Pred>
inline
RandomIt xbinary_search( RandomIt begin, RandomIt end, T const &key, Pred pred )
requires std::random_access_iterator<RandomIt>
&&
requires( Pred pred, typename std::iterator_traits<RandomIt>::value_type &elem, T const &key )
{
{ pred( elem, key ) } -> std::convertible_to<std::strong_ordering>;
}
{
using namespace std;
size_t lower = 0, upper = end - begin, mid;
strong_ordering so;
while( lower != upper )
{
mid = (lower + upper) / 2;
so = pred( begin[mid], key );
if( so == 0 )
{
assert(mid == 0 || pred( begin[mid - 1], key ) < 0);
assert(begin + mid + 1 == end || pred( begin[mid + 1], key ) > 0);
return begin + mid;
}
if( so > 0 )
upper = mid;
else
lower = mid + 1;
}
return end;
}
This code only works correctly if there's only one value between begin and end that matches the key. But if you debug and NDEBUG is not defined, the code stops in your debugger.
Having a pair of iterators [begin, end) I want to advance begin while a condition is true and I didn't reach end. As I don't know any "direct" algorithm from the standard library to do this I'm using:
std::find_if_not(begin, end, condition);
but my problem is that the name of the function does't express my intention to advance begin while the condition is true in a clear way.
Is any algorithm in the C++ standard library to advance an iterator while a condition is true?
C++14:
template<class...Args>
auto advance_while_true( Args&&... args ) {
return std::find_if_not( std::forward<Args>(args)... );
}
but really, just use find_if_not. The name might not match your description of the problem, but as a std library algorithm, it is relatively famous.
If the condition is common, write a wrapper that takes two (templetized) iterators and includes the condition inside itself.
template<class Iterator>
std::decay_t<Iterator> advance_while_foo( Iterator first, Iterator last ) {
return std::find_if_not( std::forward<Iterator>(first), std::forward<Iterator>(last),
[](auto&& x) {
return foo(x);
}
);
}
which both uses the std algorithm for the guts (meaning it will be better written than if you write it yourself probably), and gives it a name (foo) that in theory should be appropriate.
(forward and decay_t is probably overkill. Replace auto&& with the stored type const& and std::decay_t<?> with typename std::decay<?>::type if you aren't C++14.)
I think this is most easily expressed by the idiom...
while (condition (begin++));
And if you want to check against an end iterator, just add that to the conditions...
while (begin != end && condition(begin++));
It's a nice little trick (that goes back to C) because it works for things that aren't even technically iterators like...
// Consume leading whitespace
while (isspace(ch = getchar()));
This question already has answers here:
Advantages of std::for_each over for loop
(22 answers)
Closed 7 years ago.
Let's consider a template function written in C++11 which iterates over a container.
Please exclude from consideration the range loop syntax because it is not yet supported by the compiler I'm working with.
template <typename Container>
void DoSomething(const Container& i_container)
{
// Option #1
for (auto it = std::begin(i_container); it != std::end(i_container); ++it)
{
// do something with *it
}
// Option #2
std::for_each(std::begin(i_container), std::end(i_container),
[] (typename Container::const_reference element)
{
// do something with element
});
}
What are pros/cons of for loop vs std::for_each in terms of:
a) performance? (I don't expect any difference)
b) readability and maintainability?
Here I see many disadvantages of for_each. It wouldn't accept a c-style array while the loop would. The declaration of the lambda formal parameter is so verbose, not possible to use auto there. It is not possible to break out of for_each.
In pre- C++11 days arguments against for were a need of specifying the type for the iterator (doesn't hold any more) and an easy possibility of mistyping the loop condition (I've never done such mistake in 10 years).
As a conclusion, my thoughts about for_each contradict the common opinion. What am I missing here?
I think there are some other differences not yet covered by the answers so far.
a for_each can accept any appropriate callable object, allowing one to 'recycle' the loop body for different for loops. For example (pseudo code)
for( range_1 ) { lengthy_loop_body } // many lines of code
for( range_2 ) { lengthy_loop_body } // the same many lines of code again
becomes
auto loop_body = some_lambda; // many lines of code here only
std::for_each( range_1 , loop_body ); // a single line of code
std::for_each( range_2 , loop_body ); // another single line of code
thus avoiding duplication and simplifying code maintenance. (Of course, in a funny mix of styles one could also use a similar approach with the for loop.)
another difference regards breaking out of the loop (with break or return in the for loop). As far as I know, in an for_each loop this can only be done by throwing an exception. For example
for( range )
{
some code;
if(condition_1) return x; // or break
more code;
if(condition_2) continue;
yet more code;
}
becomes
try {
std::for_each( range , [] (const_reference x)
{
some code;
if(condition_1) throw x;
more code;
if(condition_2) return;
yet more code;
} );
} catch(const_reference r) { return r; }
with the same effects regarding calling of destructors for objects with scope of the loop body and the function body (around the loop).
the main benefit of for_each is, IMHO, that one can overload it for certain container types, when plain iteration is not as efficient. For example, consider a container that holds a linked list of data blocks, each block containing a contiguous array of elements, similar to (omitting irrelevant code)
namespace my {
template<typename data_type, unsigned block_size>
struct Container
{
struct block
{
const block*NEXT;
data_type DATA[block_size];
block() : NEXT(0) {}
} *HEAD;
};
}
then an appropriate forward iterator for this type would require to check for the end of block at each increment and the comparison operator needs to compare both the block pointer and the index within each block (omitting irrelevant code):
namespace my {
template<typename data_type, unsigned block_size>
struct Container
{
struct iterator
{
const block*B;
unsigned I;
iterator() = default;
iterator&operator=(iterator const&) = default;
iterator(const block*b, unsigned i) : B(b), I(i) {}
iterator& operator++()
{
if(++I==block_size) { B=B->NEXT; I=0; } // one comparison and branch
return*this;
}
bool operator==(const iterator&i) const
{ return B==i.B && I==i.I; } // one or two comparisons
bool operator!=(const iterator&i) const
{ return B!=i.B || I!=i.I; } // one or two comparisons
const data_type& operator*() const
{ return B->DATA[I]; }
};
iterator begin() const
{ return iterator(HEAD,0); }
iterator end() const
{ return iterator(0,0); }
};
}
this type of iterator works correctly with for and for_each, for example
my::Container<int,5> C;
for(auto i=C.begin();
i!=C.end(); // one or two comparisons here
++i) // one comparison here and a branch
f(*i);
but requires two to three comparisons per iteration as well as a branch. A more efficient way is to overload the for_each() function to loop on the block pointer and index separately:
namespace my {
template<typename data_type, int block_size, typename FuncOfDataType>
FuncOfDataType&&
for_each(typename my::Container<data_type,block_size>::iterator i,
typename my::Container<data_type,block_size>::iterator const&e,
FuncOfDataType f)
{
for(; i.B != e.B; i.B++,i.I=0)
for(; i.I != block_size; i.I++)
f(*i);
for(; i.I != e.I; i.I++)
f(*i);
return std::move(f);
}
}
using my::for_each; // ensures that the appropriate
using std::for_each; // version of for_each() is used
which requires only one comparison for most iterations and has no branches (note that branches can have a nasty impact on performance). Note that we don't need to define this in namespace std (which might be illegal), but can ensure that the correct version is used by appropriate using directives. This is equivalent to using std::swap; when specialising swap() for certain user-defined types.
Regarding perfomance, your for loop calls std::end repeatedly, while std::for_each will not. This might or might not result in a performance difference depending on the container used.
The std::for_each version will visit each element exactly once. Somebody reading the code can know that as soon as they see std::for_each, as there's nothing that can be done in the lambda to mess with the iterator. In the traditional for loop, you have to study the body of the loop for unusual control flow (continue, break, return) and dinking with the iterator (e.g., in this case, skip the next element with ++it).
You can trivially change the algorithm in the lambda solution. For example, you could make an algorithm that visits every nth element. In many cases, you didn't really want a for loop anyway, but a different algorithm like copy_if. Using an algorithm+lambda, is often more amenable to change and is a bit more concise.
On the flip side, programmers are much more used to traditional for loops, so they may find algorithm+lambda to be harder to read.
First, I cannot see much difference between these two, because for_each is implemented using for loop. But note that for_each is a function which has a return value.
Second, I will use range loop syntax once available in this case since this day would come soon anyway.
Indeed; in the case of using a Lambda expression, you have to declare the parameter type and name, so nothing is won.
But it will be awesome as soon as you want to call one (named) function or function-object with this. (Remember that you can combine function-like things via std::bind.)
The books from Scott Meyers (I believe it was Effective STL) describe such programming styles very good and clear.
I have two vector<T> in my program, called active and non_active respectively. This refers to the objects it contains, as to whether they are in use or not.
I have some code that loops the active vector and checks for any objects that might have gone non active. I add these to a temp_list inside the loop.
Then after the loop, I take my temp_list and do non_active.insert of all elements in the temp_list.
After that, I do call erase on my active vector and pass it the temp_list to erase.
For some reason, however, the erase crashes.
This is the code:
non_active.insert(non_active.begin(), temp_list.begin(), temp_list.end());
active.erase(temp_list.begin(), temp_list.end());
I get this assertion:
Expression:("_Pvector == NULL || (((_Myvec*)_Pvector)->_Myfirst <= _Ptr && _Ptr <= ((_Myvect*)_Pvector)->_Mylast)",0)
I've looked online and seen that there is a erase-remove idiom, however not sure how I'd apply that to a removing a range of elements from a vector<T>
I'm not using C++11.
erase expects a range of iterators passed to it that lie within the current vector. You cannot pass iterators obtained from a different vector to erase.
Here is a possible, but inefficient, C++11 solution supported by lambdas:
active.erase(std::remove_if(active.begin(), active.end(), [](const T& x)
{
return std::find(temp_list.begin(), temp_list.end(), x) != temp_list.end();
}), active.end());
And here is the equivalent C++03 solution without the lambda:
template<typename Container>
class element_of
{
Container& container;
element_of(Container& container) : container(container) {}
public:
template<typename T>
bool operator()(const T& x) const
{
return std::find(container.begin(), container.end(), x)
!= container.end();
}
};
// ...
active.erase(std::remove_if(active.begin(), active.end(),
element_of<std::vector<T> >(temp_list)),
active.end());
If you replace temp_list with a std::set and the std::find_if with a find member function call on the set, the performance should be acceptable.
The erase method is intended to accept iterators to the same container object. You're trying to pass in iterators to temp_list to use to erase elements from active which is not allowed for good reasons, as a Sequence's range erase method is intended to specify a range in that Sequence to remove. It's important that the iterators are in that sequence because otherwise we're specifying a range of values to erase rather than a range within the same container which is a much more costly operation.
The type of logic you're trying to perform suggests to me that a set or list might be better suited for the purpose. That is, you're trying to erase various elements from the middle of a container that match a certain condition and transfer them to another container, and you could eliminate the need for temp_list this way.
With list, for example, it could be as easy as this:
for (ActiveList::iterator it = active.begin(); it != active.end();)
{
if (it->no_longer_active())
{
inactive.push_back(*it);
it = active.erase(it);
}
else
++it;
}
However, sometimes vector can outperform these solutions, and maybe you have need for vector for other reasons (like ensuring contiguous memory). In that case, std::remove_if is your best bet.
Example:
bool not_active(const YourObjectType& obj);
active_list.erase(
remove_if(active_list.begin(), active_list.end(), not_active),
active_list.end());
More info on this can be found under the topic, 'erase-remove idiom' and you may need predicate function objects depending on what external states are required to determine if an object is no longer active.
You can actually make the erase/remove idiom usable for your case. You just need to move the value over to the other container before std::remove_if possibly shuffles it around: in the predicate.
template<class OutIt, class Pred>
struct copy_if_predicate{
copy_if_predicate(OutIt dest, Pred p)
: dest(dest), pred(p) {}
template<class T>
bool operator()(T const& v){
if(pred(v)){
*dest++ = v;
return true;
}
return false;
}
OutIt dest;
Pred pred;
};
template<class OutIt, class Pred>
copy_if_predicate<OutIt,Pred> copy_if_pred(OutIt dest, Pred pred){
return copy_if_predicate<OutIt,Pred>(dest,pred);
}
Live example on Ideone. (I directly used bools to make the code shorter, not bothering with output and the likes.)
The function std::vector::erase requires the iterators to be iterators into this vector, but you are passing iterators from temp_list. You cannot erase elements from a container that are in a completely different container.
active.erase(temp_list.begin(), temp_list.end());
You try to erase elements from one list, but you use iterators for second list. First list iterators aren't the same, like in second list.
I would like to suggest that this is an example of where std::list should be used. You can splice members from one list to another. Look at std::list::splice()for this.
Do you need random access? If not then you don't need a std::vector.
Note that with list, when you splice, your iterators, and references to the objects in the list remain valid.
If you don't mind making the implementation "intrusive", your objects can contain their own iterator value, so they know where they are. Then when they change state, they can automate their own "moving" from one list to the other, and you don't need to transverse the whole list for them. (If you want this sweep to happen later, you can get them to "register" themselves for later moving).
I will write an algorithm here now to run through one collection and if a condition exists, it will effect a std::remove_if but at the same time will copy the element into your "inserter".
//fwd iterator must be writable
template< typename FwdIterator, typename InputIterator, typename Pred >
FwdIterator copy_and_remove_if( FwdIterator inp, FwdIterator end, InputIterator outp, Pred pred )
{
for( FwdIterator test = inp; test != end; ++test )
{
if( pred(*test) ) // insert
{
*outp = *test;
++outp;
}
else // keep
{
if( test != inp )
{
*inp = *test;
}
++inp;
}
}
return inp;
}
This is a bit like std::remove_if but will copy the ones being removed into an alternative collection. You would invoke it like this (for a vector) where isInactive is a valid predicate that indicates it should be moved.
active.erase( copy_and_remove_if( active.begin(), active.end(), std::back_inserter(inactive), isInactive ), active.end() );
The iterators you pass to erase() should point into the vector itself; the assertion is telling you that they don't. This version of erase() is for erasing a range out of the vector.
You need to iterate over temp_list yourself and call active.erase() on the result of dereferencing the iterator at each step.
I have a collection of elements that I need to operate over, calling member functions on the collection:
std::vector<MyType> v;
... // vector is populated
For calling functions with no arguments it's pretty straight-forward:
std::for_each(v.begin(), v.end(), std::mem_fun(&MyType::myfunc));
A similar thing can be done if there's one argument to the function I wish to call.
My problem is that I want to call a function on elements in the vector if it meets some condition. std::find_if returns an iterator to the first element meeting the conditions of the predicate.
std::vector<MyType>::iterator it =
std::find_if(v.begin(), v.end(), MyPred());
I wish to find all elements meeting the predicate and operate over them.
I've been looking at the STL algorithms for a "find_all" or "do_if" equivalent, or a way I can do this with the existing STL (such that I only need to iterate once), rather than rolling my own or simply do a standard iteration using a for loop and comparisons.
Boost Lambda makes this easy.
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>
std::for_each( v.begin(), v.end(),
if_( MyPred() )[ std::mem_fun(&MyType::myfunc) ]
);
You could even do away with defining MyPred(), if it is simple. This is where lambda really shines. E.g., if MyPred meant "is divisible by 2":
std::for_each( v.begin(), v.end(),
if_( _1 % 2 == 0 )[ std::mem_fun( &MyType::myfunc ) ]
);
Update:
Doing this with the C++0x lambda syntax is also very nice (continuing with the predicate as modulo 2):
std::for_each( v.begin(), v.end(),
[](MyType& mt ) mutable
{
if( mt % 2 == 0)
{
mt.myfunc();
}
} );
At first glance this looks like a step backwards from boost::lambda syntax, however, it is better because more complex functor logic is trivial to implement with c++0x syntax... where anything very complicated in boost::lambda gets tricky quickly. Microsoft Visual Studio 2010 beta 2 currently implements this functionality.
I wrote a for_each_if() and a for_each_equal() which do what I think you're looking for.
for_each_if() takes a predicate functor to evaluate equality, and for_each_equal() takes a value of any type and does a direct comparison using operator ==. In both cases, the function you pass in is called on each element that passes the equality test.
/* ---
For each
25.1.1
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first, InputIterator last, const T& value, Function f)
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first, InputIterator last, Predicate pred, Function f)
Requires:
T is of type EqualityComparable (20.1.1)
Effects:
Applies f to each dereferenced iterator i in the range [first, last) where one of the following conditions hold:
1: *i == value
2: pred(*i) != false
Returns:
f
Complexity:
At most last - first applications of f
--- */
template< class InputIterator, class Function, class Predicate >
Function for_each_if(InputIterator first,
InputIterator last,
Predicate pred,
Function f)
{
for( ; first != last; ++first)
{
if( pred(*first) )
f(*first);
}
return f;
};
template< class InputIterator, class Function, class T>
Function for_each_equal(InputIterator first,
InputIterator last,
const T& value,
Function f)
{
for( ; first != last; ++first)
{
if( *first == value )
f(*first);
}
return f;
};
Is it ok to change the vector? You may want to look at the partition algorithm.
Partition algorithm
Another option would be to change your MyType::myfunc to either check the element, or to take a predicate as a parameter and use it to test the element it's operating on.
std::vector<int> v, matches;
std::vector<int>::iterator i = v.begin();
MyPred my_pred;
while(true) {
i = std::find_if(i, v.end(), my_pred);
if (i == v.end())
break;
matches.push_back(*i);
}
For the record, while I have seen an implementation where calling end() on a list was O(n), I haven't seen any STL implementations where calling end() on a vector was anything other than O(1) -- mainly because vectors are guaranteed to have random-access iterators.
Even so, if you are worried about an inefficient end(), you can use this code:
std::vector<int> v, matches;
std::vector<int>::iterator i = v.begin(), end = v.end();
MyPred my_pred;
while(true) {
i = std::find_if(i, v.end(), my_pred);
if (i == end)
break;
matches.push_back(*i);
}
For what its worth for_each_if is being considered as an eventual addition to boost. It isn't hard to implement your own.
Lamda functions - the idea is to do something like this
for_each(v.begin(), v.end(), [](MyType& x){ if (Check(x) DoSuff(x); })
Origial post here.
You can use Boost.Foreach:
BOOST_FOREACH (vector<...>& x, v)
{
if (Check(x)
DoStuff(x);
}