I've recently stumbled upon this wording from cppreference:
Unlike the rest of the algorithms, for_each is not allowed to make copies of the elements in the sequence even if they are trivially copyable.
Is the statement correct? I haven't found any grounds in the standard. Do I understand well, that it would btw. imply the following example from the same page invalid?
struct Sum
{
Sum(): sum{0} { }
void operator()(int n) { sum += n; }
int sum;
};
int main()
{
std::vector<int> nums{3, 4, 2, 8, 15, 267};
// ...
// calls Sum::operator() for each number
Sum s = std::for_each(nums.begin(), nums.end(), Sum());
// ...
}
That sentence on cppreference.com comes from the wording added to C++17 about the new support for parallel algorithms.
[algorithms.parallel.exec]/3 says:
Unless otherwise stated, implementations may make arbitrary copies of elements (with type
T
) from sequences whereis_trivially_copy_constructible_v<T>
andis_trivially_destructible_v<T>
are true.
Note this is in a context discussing parallel algorithms, defined as standard library function templates which have a template parameter named ExecutionPolicy
.
But then [alg.foreach]/9 says of for_each(ExecutionPolicy&&, ForwardIterator, ForwardIterator, Function)
:
Implementations do not have the freedom granted under [algorithms.parallel.exec] to make arbitrary copies of elements from the input sequence.
Presumably some parallelization techniques can be more efficient for trivial types by making copies of the elements. (Maybe to make them contiguous in memory? I'm just guessing.)
So none of this applies to the older non-parallel for_each(InputIterator first, InputIterator last, Function f)
. For that algorithm, it's simply the case that since the effects are specified as "Applies f
to the result of dereferencing every iterator in the range [first, last)
...", the functor argument must be e.g. *first
and not a copy of *first
.
The wording is indeed confusing, as it is also mentionned that
The signature of the function should be equivalent to the following:
void fun(const Type &a);
The signature does not need to have const &.
I think you need to see the fact that for_each
is not allowed to make copies of the elements as a guarantee given by the standard to the user rather than a limitation on the user predicate function applied to each element..
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With