What I want is this behavior: void change_if( ForwardIterator first, ForwardIterator last, UnaryPredicate test, UnaryOperation op )
Is the best way to achieve that just with a for loop? Or is there some STL magic I don't yet know?
This can be done without using boost but applying standard algorithm std::for_each
I do not advice to use boost for such simple tasks. It is simply a stupidy to include boost in your project that to perform such a simple task. You may use boost for such tasks provided that it is already included in your project.
std::for_each( first, last, []( const T &x ) { if ( test( x ) ) op( x ); } );
Or you can remove the qualifier const if you are going to change elements of the sequence
std::for_each( first, last, []( T &x ) { if ( test( x ) ) op( x ); } );
Sometimes when the whole range of a sequence is used it is simpler to use the range based for statement instead of an algorithm becuase using algorithms with lambda expressions sometimes makes code less readable
for ( auto &x : sequence )
{
if ( test( x ) ) op( x );
}
Or
for ( auto &x : sequence )
{
if ( test( x ) ) x = op( x );
}
The solution by Vlad from Moscow is the recommended approach for it's simplicity.
The "seemingly obious" use of the std::transform standard algorithm with a lambda:
std::transform(first, last, first, [](auto elem) {
return test(elem) ? op(elem) : elem;
});
actually leads to performance degradation because all elements will be assigned to, not just those satisfying the predicate. To only modify the predicated elements, one would also need something like boost::filter_iterator as mentioned in the answer by kiwi.
Note that I used C++14 syntax with the auto inside the lambda. For C++11, you would need something like decltype(*first) or iterator_traits<ForwardIterator>::value_type. And in C++98/03 you would both that and a hand made function object.
Still another boost solution :
http://www.boost.org/doc/libs/1_55_0/libs/iterator/doc/filter_iterator.html
Just call std::transform on your filtered iterator.
std::for_each( first, last, []( T &x ) { if ( test( x ) ) op( x ); } );
or using boost lambda:
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/if.hpp>
std::for_each( v.begin(), v.end(),
if_( test() )[ op() ]
);
alternatively:
std::vector<int>::iterator it = v.begin();
while ( it != v.end()) {
if ( test( *it)) op(*it);
++it;
}
You want change_if as a simple loop?
template<typename ForwardIterator, typename UnaryPredicate>
void change_if( ForwardIterator first, ForwardIterator last, UnaryPredicate test, UnaryOperation op ) {
for(; first!=last; ++first)
if (test(*first)) *first=op(std::move(*first));
}
or just write the above loop. I would advise actually writing change_if and calling it, because while the above code is short I would find the change_if call to be more, not less, clear than just dropping the above code in.
I also like writing container-based overloads:
template<typename Container, typename UnaryPredicate>
void change_if( Container&& c, UnaryPredicate test, UnaryOperation op ) {
for(auto& v : std::forward<Container>(c))
if (test(v)) v=op(std::move(v));
}
but I also have this:
template<typename Iterator>
struct range {
Iterator b, e;
Iterator begin() const { return b; }
Iterator end() const { return e; }
};
template<typename Iterator0, typename Iterator1>
range<typename std::decay<Iterator0>::type> make_range(Iterator0&& b, Iterator1&& e) {
static_assert(
std::is_convertible< Iterator1, typename std::decay<Iterator0>::type >::value,
"end must be compatible with begin iterator type"
);
return { std::forward<Iterator0>(b), std::forward<Iterator1>(e) };
}
which lets me use such container-based algorithms with iterators.
You'll see I have a Container based change_if? It is really a range-based change_if.
It is called like:
change_if( myVect, [](int x){return (x%2)==0;}, [](int x){return x/2;} );
on a container, not a pair of iterators. However, if you only want to change the first half of a container, it doesn't work: so at first glance, container-based (well, range-based) algorithms are less useful.
But make_range turns iterators into a range. So you can:
change_if( make_range( myVec.begin(), myVec.begin()+myVec.size()/2 ), [](int x){return (x%2)==0;}, [](int x){return x/2;} )
make_range fills in the inability to directly pass 2 iterators to range-based algorithms by bundling two iterators into one range<> object. This corner case is more verbose, but the typical case (of processing an entire container) becomes less verbose.
Plus, a common kind of error (naming a different container for begin and end) is made far less frequent.
All of this ends up being as efficient, or more so, than the iterator-based version. And, if you replace your ranges with iterables (ranges that have dissimilar begin and end iterator types), my change_if just works
Related
I'm trying to construct a set of unique words from a list of entries, each of which has a vector of strings.
So I made a function called Insert, which gets called for each of the entries like this:
for( auto & e : _Entries )
_Dictionary.Insert( begin( e.getNameWords( ) ), end( e.getNameWords( ) ) );
The class _Dictionary internally has a set (the STL container) and I wrote the function Insert as follows:
template< typename InputIterator >
void Insert( InputIterator first, InputIterator last )
{
for( auto it = first ; it != last ; ++it )
_AllWords.insert( *it );
}
In my case, calling Insert for all entries in _Entries took an average of 570 milliseconds.
Then I thought that I should use the functions that the STL already has to do the same thing that the for loop in Insert does, so I changed the function Insert to the following:
template< typename InputIterator >
void Insert( InputIterator first, InputIterator last )
{
copy( first, last, inserter( _AllWords, begin( _AllWords ) ) );
}
I was expecting this to
be more correct, and
be at least as fast, if not more
(guided by the philosophy of letting the STL do as much for you as you can). However, I was surprised to notice that this implementation actually took longer; not much more, but a consistent 200 milliseconds more than the previous for-loop based implementation.
I know this is an essentially trivial speed difference, but I'm still surprised.
So my question is: why is my implementation faster?
Note: I am compiling this with clang's version 3.5.2 with the libc++ standard library and with the -O3 flag, under Ubuntu 14.04.
The problem is this:
copy( first, last, inserter( _AllWords, begin( _AllWords ) ) );
ends up calling this version of insert:
iterator insert( iterator hint, const value_type& value );
with begin() as the hint. That is, typically, not where you're going to want to insert each value. As a result, you're just making the container do more work trying to figure out where to add your values since your hint is as bad as possible.
But note that there is also this overload of insert:
template< class InputIt >
void insert( InputIt first, InputIt last );
which you should just use†:
template< typename InputIterator >
void Insert( InputIterator first, InputIterator last )
{
_AllWords.insert(first, last);
}
And side-note, _AllWords is a reserved identifier.
†Although based on this note:
The overloads (5-6) are often implemented as a loop that calls the overload (3) with end() as the hint; they are optimized for appending a sorted sequence (such as another set) whose smallest element is greater than the last element in *this
That seems like a really specific goal to optimize against, which you may or may not satisfy, so probably you shouldn't use this overload, and your initial loop is just fine.
I have two vectors of predicates:
typedef std::function<bool(int)> pred;
vector<pred> v1;
vector<pred> v2;
I need to merge them into one, but the predicates from the second vector should be inverted (i.e. they should return true in the cases they normaly return false). So, in fact i need a kind of "inverting" wrapper.
I created an inversion function and a struct which holds an original predicate and inverts its value:
struct inverted
{
pred pr;
inverted(pred pr_) : pr(pr_) {}
bool operator () (int i) {return !pr(i);}
};
pred CreateInverted(pred pr)
{
return inverted(pr);
}
Using this, the inversion of the vector predicates might look like:
transform( v2.begin(), v2.end(), v2.begin(), CreateInverted );
But I'd like to know if there are better solutions, specially based on the Standard Library?
No C++11, Boost is allowed.
If your predicate follows certain conventions, you can use std::not1 to create the inverted predicate. Here is an example:
struct foobar : std::unary_function<bool, int>
{
bool operator()(int value) const { return value > 42; }
};
do_something_if(values.begin(), values.end(), std::not1(foobar());
The standard library has a std::not1 predicate that takes a unary predicate and yields the negation of the argument, so there is no need to provide your own functor for this [code is not tested, you might need to correct the syntax]:
std::transform( v.begin(), v.end(), v.begin(),
std::not1< std::function<bool(int)> > );
I can't think of a better way to solve your problem.
You actually use a transformer function together with the stl::transform which should be used exactly for your purpose.
This is considerable almost reference code!
What is the C++ idiomatic way of creating a std::vector from the last n elements of a std::map?
I am not interested in preserving the order in the vector.
I can copy the elements, like this:
std::map< double, MyType > m;
size_t n = 3;
std::vector< MyType > v;
std::map< double, MyType >::iterator it = m.end();
while ( n-- ) { // assuming m.size() >= n
it--;
v.push_back(it->second);
}
But, is there any other way, more idiomatic, to do it?
std::copy would be suitable if you wanted to copy the types unchanged. However, std::map<T,U>::iterator_type::value_type is not U (the type you want to copy), but std::pair<T,U> (in other words, dereferencing a map iterator yields a pair of the key and value types), so a raw copy won't work.
So we need to copy the elements, performing a transformation along the way. That's what std::transform is for.
For convenience, I'm going to assume that your compiler supports C++11 lambda expressions and the auto keyword. If not, it can be fairly trivially rewritten as a functor. But we're looking for something roughly like this:
std::transform(map_first, map_last, std::back_inserter(vec), [](std::pair<double,MyType> p) { return p.second; });
Now we just need to fill in the two first parameters:
auto map_first = std::next(map.end(), -n);
auto map_last = map.end();
The only tricky part here is that map iterators are bidirectional, but not random-access, so we can't simply say map.end() - n. The - operator is not defined. Instead, we have to use std::next (which takes linear rather than constant time for bidirectional operators, but there's no way around that).
(Note, I haven't tried compiling this code, so it might require a small bit of tweaking)
std::transform would be the most idiomatic way. You need a functional
object:
template<typename PairType>
struct Second
{
typename PairType::second_type operator()( PairType const& obj ) const
{
return obj.second;
}
}
(If your doing much work with std::map or other things that use
std::pair, you'll have this in your toolbox.)
After that, it's a bit awkward because you only want the last n. Since
iterators into a map are not random access iterators, and you can't add
or subtract arbitrary values, the simplest solution is to copy them all,
then remove the ones you don't want:
std::vector<MyType>
extractLastN( std::map<double, MyType> const& source, size_t n )
{
std::vector<MyType> results;
std::transform( source.begin(), source.end(),
std::back_inserter( results ),
Second<std::map<double, MyType>::value_type>() );
if ( results.size() > n ) {
results.erase( results.begin(), results.end() - n );
}
return results;
}
This isn't the most efficient, but depending on n and where it is
used, it may be sufficient. If you do want to avoid the extra copying,
etc. (probably worthwhile only if n is typically much smaller than the
size of the map), you'll have to do something fancier:
std::vector<MyType>
extractLastN( std::map<double, MyType> const& source, ptrdiff_t n )
{
std::map<double, MyType>::const_iterator start
= source.size() <= n
? source.begin()
: std::prev( source.end(), n );
std::vector<MyType> results;
std::transform( start, source.end(),
std::back_inserter( results ),
Second<std::map<double, MyType>::value_type>() );
return results;
}
(If you don't have access to C++11, std::prev is simply:
template<typename IteratorType>
IteratorType
prev( IteratorType start, ptrdiff_t n )
{
std::advance( start, -n );
return start;
}
Again, if you're doing much with the standard library, you probably
already have it in your toolkit.)
Here's a simple Boost.Range version:
#include <boost/range/iterator_range_core.hpp>
#include <boost/range/adaptor/map.hpp>
//#include <boost/range/adaptor/reversed.hpp> // comment in for 'reversed'
#include <map>
#include <vector>
struct X{};
int main(){
std::map<int, X> m;
unsigned n = 0;
auto vec(boost::copy_range<std::vector<X>>(
boost::make_iterator_range(m, m.size()-n, 0)
| boost::adaptors::map_values
//| boost::adaptors::reversed // comment in to copy in reverse order
));
}
One way of doing it is using a simple for_each:
map<int,double> m;
vector<double> v;
//Fill map
auto siter = m.end();
advance(siter, -3);
for_each(siter, m.end(), [&](pair<int,double> p) { v.push_back(p.second); });
EDIT Even simpler way is using std::prev with for_each:
map<int,double> m;
vector<double> v;
//Fill map
for_each(prev(m.end(), 3), m.end(),
[&](pair<int,double> p) { v.push_back(p.second); });
Also, if you want fill the vector in reverse order you can use:
for_each(m.rbegin(), next(m.rbegin(), 3),
[&](pair<int,double> p) { v.push_back(p.second); });
First, what do we want to write to be idiomatic? I suggest:
std::vector<Mytype> v;
v.reserve(n);
std::transform(
limited(n, m.rbegin()),
limited_end(m.rend()),
std::back_inserter(v),
values_from(m)
);
Now we just have to make that code valid.
We can replace values_from(m) with a lambda (which doesn't need m), or implement it using James Kanze's class Second (in which case m is there for type deduction):
template <typename Map>
Second<Map::value_type> values_from(const Map &) {
return Second<Map::value_type>();
}
Implementing limited is a bit of a pain. It's a template function that returns an iterator. The iterator type it returns is a template that wraps another iterator type, and forwards everything on to it except that it keeps track of n, and acts like an end iterator when it has been advanced n times. limited_end returns an end iterator of the same type, so it compares equal either if the underlying iterators are equal, or if one of the iterators was created with limited_end and the other one has run n down to zero.
I don't have the code for this handy, but it's basically how you get _n equivalents of all the standard algorithms, not just copy_n. In this case, we want transform_n, but there isn't one.
An alternative to transform would be to use copy_n with a boost::transform_iterator wrapped around m.rbegin(). I won't do that here either, because I always have to check the docs to use transform_iterator.
Do it backwards:
assert(n <= m.size());
std::copy(m.rbegin(), m.rbegin()+n, std::back_inserter(v));
bidirectional iterators FTW.
OK, I obviously wasn't awake yet, and that was wishful thinking. I still prefer walking backwards to get the last n though, so a working version looks like this:
#include <map>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
// I'm assuming it's ok to copy min(m.size(), n)
template <typename Iter>
Iter safe_advance(Iter begin, Iter const &end, int distance)
{
while(distance-- > 0 && begin != end)
++begin;
return begin;
}
void copy_last_n(map<double,int> const &m,
vector<int> &v, int n)
{
transform(m.rbegin(), safe_advance(m.rbegin(), m.rend(), n),
back_inserter(v),
[](map<double,int>::value_type const &val)
{
return val.second;
}
);
}
James Kanze already wrote the Second functor - use that if you don't have access to lambdas.
The C++ std algorithms define a number of algorithms that take an input and an output sequence, and create the elements of the output sequence from the elements of the input sequence. (Best example being std::transform.)
The std algorithms obviously take iterators, so there's no question that the container for the OutputIterator has to exist prior to the algorithm being invoked.
That is:
std::vector<int> v1; // e.g. v1 := {1, 2, 3, 4, 5};
std::vector<int> squared;
squared.reserve(v1.size()); // not strictly necessary
std::transform(v1.begin(), v1.end(), std::back_inserter(squared),
[](int x) { return x*x; } ); // λ for convenience, needn't be C++11
And this is fine as far as the std library goes. When I find iterators too cumbersome, I often look to Boost.Range to simplify things.
In this case however, it seems that the mutating algorithms in Boost.Range also use OutputIterators.
So I'm currently wondering whether there's any convenient library out there, that allows me to write:
std::vector<int> const squared = convenient::transform(v1, [](int x) { return x*x; });
-- and if there is none, whether there is a reason that there is none?
Edit: example implementation (not sure if this would work in all cases, and whether this is the most ideal one):
template<typename C, typename F>
C transform(C const& input, F fun) {
C result;
std::transform(input.begin(), input.end(), std::back_inserter(result), fun);
return result;
}
(Note: I think convenient::transform will have the same performance characteristics than the handwritten one, as the returned vector won't be copied due to (N)RVO. Anyway, I think performance is secondary for this question.)
Edit/Note: Of the answers(comments, really) given so far, David gives a very nice basic generic example.
And Luc mentions a possible problem with std::back_inserter wrt. genericity.
Both just go to show why I'm hesitating to whip this up myself and why a "proper" (properly tested) library would be preferable to coding this myself.
My question phrased in bold above, namely is there one, or is there a reason there is none remains largely unanswered.
This is not meant as an answer to the question itself, it's a complement to the other answers -- but it wouldn't fit in the comments.
well - what if you wanted list or deque or some other sequence type container - it's pretty limiting.
namespace detail {
template<typename Iter, typename Functor>
struct transform {
Iter first, last;
Functor functor;
template<typename Container> // SFINAE is also available here
operator Container()
{
Container c;
std::transform(first, last, std::back_inserter(c), std::forward<Functor>(functor));
return c;
}
};
} // detail
template<typename Iter, typename Functor>
detail::transform<Iter, typename std::decay<Functor>::type>
transform(Iter first, Iter last, Functor&& functor)
{ return { first, last, std::forward<Functor>(functor) }; }
While this would work with a handful of containers, it's still not terribly generic since it requires that the container be 'compatible' with std::back_inserter(c) (BackInsertable?). Possibly you could use SFINAE to instead use std::inserter with c.begin() if c.push_back() is not available (left as an exercise to the reader).
All of this also assume that the container is DefaultConstructible -- consider containers that make use of scoped allocators. Presumably that loss of genericity is a feature, as we're only trying to cover the 'simplest' uses.
And this is in fact while I would not use such a library: I don't mind creating the container just outside next to the algorithm to separate the concerns. (I suppose this can be considered my answer to the question.)
IMHO, the point of such an algorithm is to be generic, i.e. mostly container agnostic. What you are proposing is that the transform function be very specific, and return a std::vector, well - what if you wanted list or deque or some other sequence type container - it's pretty limiting.
Why not wrap if you find it so annoying? Create your own little utilities header which does this - after all, it's pretty trivial...
The Boost.Range.Adaptors can be kind of seen as container-returning algorithms. Why not use them?
The only thing that needs to be done is to define a new range adaptor create<T> that can be piped into the adapted ranges and produces the desired result container:
template<class T> struct converted{}; // dummy tag class
template<class FwdRange, class T>
T operator|(FwdRange const& r, converted<T>){
return T(r.begin(), r.end());
}
Yep, that's it. No need for anything else. Just pipe that at the end of your adaptor list.
Here could be a live example on Ideone. Alas, it isn't, because Ideone doesn't provide Boost in C++0x mode.. meh. In any case, here's main and the output:
int main(){
using namespace boost::adaptors;
auto range = boost::irange(1, 10);
std::vector<int> v1(range.begin(), range.end());
auto squared = v1 | transformed([](int i){ return i * i; });
boost::for_each(squared, [](int i){ std::cout << i << " "; });
std::cout << "\n========================\n";
auto modded = squared | reversed
| filtered([](int i){ return (i % 2) == 0; })
| converted<std::vector<int>>(); // gimme back my vec!
modded.push_back(1);
boost::for_each(modded, [](int i){ std::cout << i << " "; });
}
Output:
1 4 9 16 25 36 49 64 81
========================
64 36 16 4 1
There is no one and correct way of enabling
std::vector<int> const squared =
convenient::transform(v1, [](int x) { return x*x; });
without a potential performance cost. You either need an explicit
std::vector<int> const squared =
convenient::transform<std::vector> (v1, [](int x) { return x*x; });
Note the explicit mentioning of the container type: Iterators don't tell anything about the container they belong to. This becomes obvious if you remind that a container's iterator is allowed by the standard to be an ordinary pointer.
Letting the algorithm take a container instead of iterators is not a solution, either. That way, the algorithm can't know how to correctly get the first and last element. For example, a long int-array does not have methods for begin(), end() and length(), not all containers have random access iterators, not operator[] defined. So there is no truly generic way to take containers.
Another possibility that allows for container-agnostic, container-returning algorithms would be some kind of generic factory (see live at http://ideone.com/7d4E2):
// (not production code; is even lacking allocator-types)
//-- Generic factory. -------------------------------------------
#include <list>
template <typename ElemT, typename CacheT=std::list<ElemT> >
struct ContCreator {
CacheT cache; // <-- Temporary storage.
// Conversion to target container type.
template <typename ContT>
operator ContT () const {
// can't even move ...
return ContT (cache.begin(), cache.end());
}
};
Not so much magic there apart from the templated cast operator. You then return that thing from your algorithm:
//-- A generic algorithm, like std::transform :) ----------------
ContCreator<int> some_ints () {
ContCreator<int> cc;
for (int i=0; i<16; ++i) {
cc.cache.push_back (i*4);
}
return cc;
}
And finally use it like this to write magic code:
//-- Example. ---------------------------------------------------
#include <vector>
#include <iostream>
int main () {
typedef std::vector<int>::iterator Iter;
std::vector<int> vec = some_ints();
for (Iter it=vec.begin(), end=vec.end(); it!=end; ++it) {
std::cout << *it << '\n';
}
}
As you see, in operator T there's a range copy.
A move might be possible by means of template specialization in case the target and source containers are of the same type.
Edit: As David points out, you can of course do the real work inside the conversion operator, which will come at probably no extra cost (with some more work it can be done more convenient; this is just for demonstration):
#include <list>
template <typename ElemT, typename Iterator>
struct Impl {
Impl(Iterator it, Iterator end) : it(it), end(end) {}
Iterator it, end;
// "Conversion" + Work.
template <typename ContT>
operator ContT () {
ContT ret;
for ( ; it != end; ++it) {
ret.push_back (*it * 4);
}
return ret;
}
};
template <typename Iterator>
Impl<int,Iterator> foo (Iterator begin, Iterator end) {
return Impl<int,Iterator>(begin, end);
}
#include <vector>
#include <iostream>
int main () {
typedef std::vector<int>::iterator Iter;
const int ints [] = {1,2,4,8};
std::vector<int> vec = foo (ints, ints + sizeof(ints) / sizeof(int));
for (Iter it=vec.begin(), end=vec.end(); it!=end; ++it) {
std::cout << *it << '\n';
}
}
The one requirement is that the target has a push_back method. Using std::distance to reserve a size may lead to sub-optimal performance if the target-container-iterator is not a random-access one.
Again, a no-answer, but rather a follow up from the comments to another answer
On the genericity of the returned type in the questions code
The code as it stands does not allow the conversion of the return type, but that can be easily solvable by providing two templates:
template <typename R, typename C, typename F>
R transform( C const & c, F f ) {_
R res;
std::transform( c.begin(), c.end(), std::back_inserter(res), f );
return res;
}
template <typename C, typename F>
C transform( C const & c, F f ) {
return transform<C,C,F>(c,f);
}
std::vector<int> src;
std::vector<int> v = transform( src, functor );
std::deque<int> d = transform<std::deque<int> >( src, functor );
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);
}