
Why std::bind can’t be formally deprecated - ingve
http://www.sdowney.org/2017/06/why-stdbind-cant-be-formally-deprecated/
======
saurik
The point being made here is heavily obfuscated to my eye due to the seemingly
needless use of std::invoke when working with the lambda cases (which, even if
useful for some reason, is not needed to make the point of this article), but
when I finally figured out what is being requested all I could think of is
"that functionality of std::bind is horrific and surprising and despite going
into this article thinking that of course bind solves a slightly different
problem to lambdas in a more readable way, you have now convinced me that
std::bind should be deprecated ASAP" (though as it came into existence in the
same version of C++ as lambda functions, I mostly end up questioning why it
ever existed).

Essentially, in order to provide something that sort of feels like lambda
functions, but entirely in templates, the placeholder arguments do not end up
locked to a single expression--instead of returning something semantically
like a function, std::bind returns something that might be better described as
a partial syntax tree that happens to be something you can call as a function,
at which point it is only then wrapped up as a function and all subexpression
parameters are bound to arguments--and so if you bind something and include in
it a bound function, that function is not passed as a value like you would
expect: its parameter is hoisted and it becomes a call expression in the new
bound composite. The author likes this behavior for some reason, but I can't
figure out why it would ever be considered to be a feature and it is trivially
simulated with lambdas (while the opposite is not true).

~~~
comex
I don’t think it’s that the author _likes_ the behavior, but that the author
has in mind some rule where features can’t be deprecated unless it’s possible
to write a purely mechanical migration tool. Not sure where that rule comes
from or why it exists.

~~~
Karellen
Yeah, that's the biggest question that came to my mind too. Why can't you
deprecate something that needs fixing up manually?

~~~
CJefferson
The idea is that if you want to deprecate something, you should tell people
how to fix their code, so they can get working again with minimal work.

However, even if it could be fixed up, I don't think it will get deprecated.

C++ is (rightly in my mind) extremely cautious about removing things -- it's
easy to ignore std::bind, it's just a library function. On the other hand, I'd
be annoyed if my perfectly working C++ code base I've been building over 10
years just broke one day. One thing I love about C++ and C is that I can leave
my code for 5 or even 10 years, come back, and expect it to still work just
fine.

~~~
Karellen
Hang on, deprecated != removed. Deprecated just means "do not use in new
code", and you'll probably get a diagnostic by default for existing uses,
which you might even be able to turn off with a compiler switch.

Also, not being able to create an automated tool to rewrite someone's code is
not the same as not being able to tell them how to fix the code themselves.

~~~
gknoy
> Deprecated just means "do not use in new code"

I originally learned that "deprecated" was meant to indicate that the language
no longer promised to include that feature in a future version. So, it still
works now, but this is your warning that you should be moving away from it.

~~~
kazinator
Merriam-Webster gives these meanings for "deprecate": "to pray against
something, such as an evil (archaic)", "to avert", "to play down" (e.g. one's
talent), "to express disapproval of, to disparage".

~~~
kazinator
How this definition is relevant is that the word is used specifically for
features that are _looked down upon_ as being harmful in some way, and so
using them in programs is creates some kind of risk in addition to "this won't
build when it goes away".

The dictionary meaning which comes into play in the software maintenance use
of "deprecated" is that "disapprove/disparage" one.

Something that will be removed because it is unfashionable, and being replaced
by shiny new idioms, is "obsolescent". Rather than abruptly removing such
features, we phase them through an obsolescence period.

Deprecated example: the C gets function (almost impossible to use without
creating a security hole, now removed from ISO C).

Obsolescent example: bzero function. (Appears in tradtional BSD sockets
networking code, superseded by memset).

------
kevingadd
Am I misunderstanding or does this example from the post:

    
    
        auto g1 = std::bind(g, _1);
        auto f2 = std::bind(f, _1, g1, 4);
        f2(10); // calls f(10, g(10), 4);
    

Imply that function values in a bind's argument list are silently converted
into function invocations? Doesn't this mean you can't pass functions around?
Why would you break fundamental assumptions about the type system like this?

The way placeholder values seem to silently propagate across nested binds is
also super gross. This stuff doesn't seem composable at all and it seems like
it shouldn't have made it into any standard.

~~~
gpderetta
Bind is a stripped down version of boost.lambda [1] which is a generalized DSL
for arbitrary expressions. Boost.lambda had, among other things, ways to
protected nested binds calls and introduce new scopes for placeholders.

Adding special magic for nested binds (which is used about 0% of the time)
was, in hindsight, a big mistake, but when bind was designed and added to the
standard, lambda expressions were many years away, so any syntactic sugar that
would ease the pain of higher order programming was very welcome.

[1] Although I don't recall who came first. Likely boost.bind was first, then
boost.lambda improved on it and some of the improvements were fed back into
bind. In fact boost.bind still has some features that std::bind doesn't have
(and viceversa).

------
rileymat2
An example from the article:

auto f1 = std::bind(f, 2, n, _1);

f1(10); // calls f(2, 5, 10);

auto l1 = [ p1 = 2, p2 = n ](auto _1) { return std::invoke(f, p1, p2, _1); };

l1(10);

It seems to me std::bind is a lot cleaner syntactically.

~~~
plorkyeran
That's a literal translation of what std::bind() is doing that no one would
actually write. `[n](auto a) { return f(2, n, a); }` is a more realistic way
to write that lambda.

~~~
jlarocco
bind() is still the cleaner way to write it.

Seeing std::bind tells me that the intention is to create a function that does
nothing but call a second function with certain parameters fixed.

A lambda expression is far more general, so when I see it I have to think
about what it's doing. There's also a subtle implication that the author chose
the more general technique for a reason. It'll raise the questions, "Why isn't
this using std::bind()?", "Is there something else going on here?", etc.

Off hand, I can't think of a reason why the bind would be any less efficient
than the lambda.

------
cjhanks
I have never seen that idiom used intentionally, I would almost always suspect
it to be an accident... but perhaps there are valid use cases in function
composition.

The more likely reason it cannot be deprecated... people actively use it and
like it.

In either case, nice find.

------
eej71
The link does not work...

~~~
Rexxar
Web archive link:
[https://web.archive.org/web/20170703000145/http://www.sdowne...](https://web.archive.org/web/20170703000145/http://www.sdowney.org/2017/06/why-
stdbind-cant-be-formally-deprecated/)

~~~
gpvos
Wow, I thought that the Wayback machine had a half-year delay in making pages
available.

------
gpderetta
>It’s sub-optimal because it has to type-erase, where a lambda allows the
compiler to do much better

Bind doesn't have to type erase nor in fact does on any of the implementations
I'm familiar of.

------
Avery3R
I'm getting a 404

~~~
gpvos
Yes, it looks like the article has been deleted. Google cache still has it,
for now:
[http://webcache.googleusercontent.com/search?q=cache:JSFVLgB...](http://webcache.googleusercontent.com/search?q=cache:JSFVLgBejAUJ:www.sdowney.org/2017/06/why-
stdbind-cant-be-formally-deprecated/+&cd=2&hl=en&ct=clnk&gl=en)

