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