What's a good implementation of applying a unary function to some elements of a vector?
I would like to apply a function UnaryFunction f
to some elements of the std container, given a predicate UnaryPredicate p
- the kind of what you would get if you concatenated std::partition
and then apply std::for_each
to one of the sections.
I'm new to C ++ so forgive my ignorance. However, I have searched for a suitable implementation in <algorithm>
but I cannot find the function I need.
Based on the possible implementations above cppreference.com I ended up with this:
template<class InputIt, class UnaryPredicate, class UnaryFunction>
UnaryFunction for_each_if(InputIt first, InputIt last, UnaryPredicate p, UnaryFunction f)
{
for (; first != last; ++first) {
if (p(*first))
{
f(*first);
}
}
return f;
}
The return value is modeled as std::for_each
though OutputIter
it might have been a better choice. This would require a more confusing implementation, and so I chose brevity this time. The alternative implementation is left as an exercise for the reader.
My question is, is there an already installed way to do this in the std library? If not, would that be a reasonable implementation of such a function pattern?
source to share
The STL does not support composition of algorithms very well. As you said, you can call first partition
and then call for_each
on one of the sections if you don't need the order of the elements.
For a new project or one where you can submit libraries, I highly recommend taking a look at the range library, for example. Boost.Range or Eric Niebler range-v3 .
In the range library, this can be done like this:
template<typename R, typename P, typename F>
F for_each_if(R& rng, P pred, F f)
{
using namespace boost::adaptors;
return (rng | filtered(pred) | for_each(f));
}
source to share
As far as the comments are concerned, there seems to be no implementation in this library. However, as user 2672165 points out, a predicate can easily be included in a function. To illustrate this, see the following modified version of the example for_each
at cppreference.com :
#include <vector>
#include <algorithm>
#include <iostream>
struct Sum {
Sum() { sum = 0; }
void operator()(int n) { sum += n; }
int sum;
};
int main()
{
std::vector<int> nums{3, 4, 2, 9, 15, 267};
std::cout << "before: ";
for (auto n : nums) {
std::cout << n << " ";
}
std::cout << '\n';
std::for_each(nums.begin(), nums.end(), [](int &n){ if (n > 5) n++; });
// Calls Sum::operator() for each number
Sum s = std::for_each(nums.begin(), nums.end(), Sum());
std::cout << "after: ";
for (auto n : nums) {
std::cout << n << " ";
}
std::cout << '\n';
std::cout << "sum: " << s.sum << '\n';
}
Here the predicate is added to the function, so it [](int &n){ n++; }
now becomes [](int &n){ if (n > 5) n++; }
to apply this function only to integer elements greater than 5.
Expected Result
before: 3 4 2 9 15 267
after: 3 4 2 10 16 268
sum: 303
Hope this helps someone else.
source to share