Reputation: 385
Is there a way to have a return value from the function that I pass to foreach.
For ex: I have,
void myfunction (int i)
{
cout << " " << i;
}
vector<int> myvector;
myvector.push_back(10);
for_each (myvector.begin(), myvector.end(), myfunction);
Lets say, I want to count the number of elements in the vector using some rule, I want to have a return value from myFunction, is this possible?
Upvotes: 3
Views: 1624
Reputation: 248199
You can adapt std::for_each
to do this as GMan showed.
But a better solution is to use the correct algorithm.
You should be able to use std::count
or std::count_if
, or perhaps std::accumulate
.
These allow you to return one result for processing the entire sequence.
Alternatively std::transform
allows you to return a result for each element in the sequence, creating a new output sequence containing the results.
Upvotes: 1
Reputation: 13201
No. But you can make myfunction
a functor, pass it a pointer to some memory, and store your return value through that pointer.
struct MyFunctor {
int *count;
MyFunctor(int *count_) : count(count_) { }
void operator()(int n) {
if (n > 5) (*count)++;
}
};
int main() {
vector<int> vec;
for (int i=0; i<10; i++) vec.push_back(i);
int count = 0;
for_each(vec.begin(), vec.end(), Myfunctor(&count));
printf("%d\n", count);
return 0;
}
Edit: As the comments have pointed out, my first example would've failed as for_each
would have made a copy of MyFunctor
, so we couldn't have retrieved the return value from our original object. I've fixed along the lines of the original approach; but you really should look at GMan's solution which is more elegant. I'm not sure about the portability, but it does work on my gcc
(4.4.2). And as the others have mentioned, whenever possible, use what <algorithm>
provides.
Upvotes: 5
Reputation: 300179
Okay, I fear that you chose your example badly when you picked up a counting problem...
The problem is that for_each
is extremely general and more specific algorithms exist for particular implementation (count
, accumulate
, transform
, ...)
So let's pick up another example: for_each
is typically used to apply a mutating operation on the objects it treats. It does not prevent you to collect statistics while doing so.
We have to take care, though for_each
does return a Predicate
object, there is no guarantee that this object was used on every item in the range. The implementation is free to copy the predicate around and use copies on part of the range... so the copy you are finally returned could be off the bat.
class Predicate
{
public:
Predicate(size_t& errors) : m_errors(errors) {}
void operator()(MyObject& o)
{
try { /* complicated */ } catch(unfit&) { ++m_errors; }
}
private:
size_t& m_errors;
};
std::vector<MyObject> myVec;
// fill myVec
size_t errors = 0;
std::for_each(myVec.begin(), myVec.end(), Predicate(errors));
The trick here is that all copies of the original predicate will point to the same size_t
variable, thus this variable has been correctly updated.
Upvotes: 1
Reputation:
std::for_each
isn't designed for that. Use std::count
to count the number of elements which is equal to some value, or std::count_if
to count the elements which satisfies some predicate:
std::vector<SomeType> vec;
std::count(vec.begin(), vec.end(), SomeType(9));
/*or */
bool myfunc(const SomeType& v)
{
return v == 9;
}
std::count_if(vec.begin(), vec.end(), f);
If you just want to copy the contents of a container to an ostream object like std::cout
, use std::copy instead:
std::vector<SomeType> vec;
...
std::copy(vec.begin(), vec.end(), \
std::ostream_iterator<SomeType>(std::cout," "));
If you need the return value from each invocation of the function, use std::transform
:
std::vector<SomeType> src;
std::vector<SomeType> result;
int myfunc(int val)
{
...
}
std::transform(src.begin(), src.end() \
result.begin(), myfunc);
std::transform
is also overloaded so it works for binary functions as well as unary functions.
Upvotes: 1
Reputation: 1311
If you want powerful foreach there is BOOST_FOREACH makro. Also boost is mostly header library so you can include only boost_foreach.hpp (afair) to your project. Example:
BOOST_FOREACH( int & i , my_vector )
{
i = 0;
}
My_vector can be vector<int>
or int[]
or any other kind of iterator.
Upvotes: 3
Reputation: 139681
It's doable:
int main()
{
std::vector<int> v;
for (int i = 1; i <= 10; i++)
v.push_back(i);
int hits = 0;
CountEven evens(&hits);
std::for_each(v.begin(), v.end(), evens);
std::cout << "hits = " << hits << std::endl;
return 0;
}
But look at the nasty implementation of CountEvens
:
class CountEven {
public:
CountEven(int *hits) : hits(hits) {}
CountEven(const CountEven &rhs) : hits(rhs.hits) {}
void operator() (int n) { if (n % 2 == 0) ++*hits; }
private:
int *hits;
};
Note that the copy constructor causes multiple instances to share the same pointer.
Use std::count
or std::count_if
.
Upvotes: 0
Reputation: 2614
Take a look at <algorithm>.
I think std::count_if is the one you are looking for.
Upvotes: 0
Reputation: 504203
for_each
will return a copy of the functor you passed it. This means you could do this:
template <typename T>
class has_value
{
has_value(const T& pValue) : mValue(pValue), mFlag(false) {}
void operator()(const T& pX)
{
if (pX == mValue)
mFlag = true;
}
operator bool(void) const { return mFlag; }
private:
T mValue;
bool mFlag;
};
bool has_seven = std::for_each(myvector.begin(), myvector.end(), has_value<int>(7));
For example. But for counting and the like, check out algorithm
and see if your function already exists. (Like count
)
Upvotes: 9
Reputation: 41351
There is a special-purpose std::count
(count occurrences of a value) and std::count_if
(count when predicate returns true) for that. Don't abuse std::for_each
for what it was not intended for.
Upvotes: 13