std::for_each
accepts and returns a functor by value:
template< class InputIt, class UnaryFunction >
UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
Although the functor can be moved in and moved out, I'm interested whether there can be no object construction involved at all. If I declare my own my_for_each
like this:
template< class InputIt, class UnaryFunction >
UnaryFunction&& my_for_each( InputIt first, InputIt last, UnaryFunction&& f);
And inside my_for_each
, call f
with std::forward<UnaryFunction>(f)(...)
, I can avoid the cost to move construct the parameter, and as a bonus be able to respect ref-qualifiers. But I'm not really sure what I should return. If I do:
return std::forward<UnaryFunction>(f);
Can bad things (e.g., dangling references) happen?
(This question comes up when I'm designing the for_each
in this post.)
As the other fine answer noted, passing const&
and rvalue reference parameters through is dangerous, as reference lifetime extension does not commute.
The proper thing to return when you want to pass a forwarding reference T&&
through is T
. This turns an rvalue into a temporary, and leaves lvalues as references.
So:
template< class InputIt, class UnaryFunction >
UnaryFunction my_for_each( InputIt first, InputIt last, UnaryFunction&& f);
Which for temporary f
creates a (moved-to) copy.
If you store this copy, it will be elided into the storage, so zero additional cost. Unless you do not store it, and move is expensive, this is basically optimal.
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