As mentioned in a similarly worded question (Why use bind over lambdas in c++14?) The answer was - no reason (and also mentioned why it would be better to use lambdas).
My question is - if in C++14 there was no longer a reason to use bind, why did the standards committee found it necessary to add std::bind_front
in C++20?
Does it now have any new advantage over a lambda?
bind_front
binds the first X parameters, but if the callable calls for more parameters, they get tacked onto the end. This makes bind_front
very readable when you're only binding the first few parameters of a function.
The obvious example would be creating a callable for a member function that is bound to a specific instance:
type *instance = ...; //lambda auto func = [instance](auto &&... args) -> decltype(auto) {return instance->function(std::forward<decltype(args)>(args)...);} //bind auto func = std::bind_front(&type::function, instance);
The bind_front
version is a lot less noisy. It gets right to the point, having exactly 3 named things: bind_front
, the member function to be called, and the instance on which it will be called. And that's all that our situation calls for: a marker to denote that we're creating a binding of the first parameters of a function, the function to be bound, and the parameter we want to bind. There is no extraneous syntax or other details.
By contrast, the lambda has a lot of stuff we just don't care about at this location. The auto... args
bit, the std::forward
stuff, etc. It's a bit harder to figure out what it's doing, and it's definitely much longer to read.
Note that bind_front
doesn't allow bind
's placeholders at all, so it's not really a replacement. It's more a shorthand for the most useful forms of bind
.
The paper that proposed it Simplified partial function application has some good compelling use cases. I will summarize them here, because otherwise I would have to quote most of the paper, so definitely go check it out:
Using a lambda would involve std::forward
boilerplate
In case of storing object by value std::bind
and std::bind_front
propagate constness, but in the case of capturing lambda the user must chose a mutable or const version creating problems
Using a lambda would involve -> decltype(auto)
boilerplate on the user side.
Like preserving mutability, except now we are talking about lvalue/rvalue and only std::bind_front
does this correctly
A consequence of propagating mutability and preserving value category
This is especially more important now since exception specification is now part of type system
cppreference has some useful notes as well:
This function is intended to replace std::bind. Unlike std::bind, it does not support arbitrary argument rearrangement and has no special treatment for nested bind-expressions or std::reference_wrappers. On the other hand, it pays attention to the value category of the call wrapper object and propagates exception specification of the underlying call operator.
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