The std::function
type erasure constructor is defined as:
template< class F >
function( F f );
The assignment operator is defined as:
template< class F >
function& operator=( F&& f );
(source cppreference)
Why does the constructor gets f
by value while operator=
gets f
by forwarding reference?
I can only guess, but I would guess it is because it was added to C++ while rvalue references and forwarding references where being added to the language.
So some parts of its API got forwarding references, and some did not.
There is one minor advantage: if the copy constructor of F
could throw while the move cannot, std::function( F )
can be guaranteed not to throw, while std::function( F const& )
cannot be. The difference is that the copy would be done outside the constructor in the template<class F> function(F)
case, but inside the constructor in the template<class F> function(F&&)
case when passed a non-rvalue.
This is not a compelling reason.
It would also make it marginally easier to specify the SFINAE behavior of function(F)
, but that wasn't formalized until long after C++11, so that cannot be the reason.
The cost to template<class F>function(F)
is low -- one move of F
over the perfect forwarding version -- so it probably hasn't been high on anyone's priority list to change (especially because it causes a subtle change in the "could throw" tests of function(F)
, and hence could actually in theory cause some strange code to break).
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