Reputation: 760
A lot of places in the STL and elsewhere you see code like this:
template <typename Func>
void foo(Func f)
{
// ...
f();
}
i.e. the callable parameter f
is passed by (copy of) value. Why is this seemingly preferred over typing the parameter as Func&
, const Func&
, or Func&&
?
Upvotes: 3
Views: 468
Reputation: 154005
The simple reason is that you can turn a value of a deduced type to use reference semantics, e.g., by passing std::ref(x)
instead of x
to the function. Obviously, for things which have more interesting operations than a function call operator you may need to use a custom wrapper but in general it is straight forward to write a wrapper for a class which give reference semantics to a value type.
On the other hand, once you are in a reference world, there is no way to undo this referencing under the control of the caller. Any reasonable generic function which receives a reference for an object cannot assume that the object behind this reference actually has exactly the referenced type but rather has to assume that the objects would get sliced to their base class. Thus, it can't just copy an argument received, for example, as Func&
to a Func
by copying it.
Taking these two realizations together pass by value for deduced types is the obvious choice for entities which may be copied in the implementation of the generic function. Note that this reasoning applies generally to arguments passed to generic functions not just to callable arguments.
Upvotes: 1