Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there a difference between std::function constructor or assignment?

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?

like image 667
RTempete Avatar asked Sep 13 '16 13:09

RTempete


1 Answers

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).

like image 51
Yakk - Adam Nevraumont Avatar answered Oct 05 '22 12:10

Yakk - Adam Nevraumont