I've seen on cppreference that std::function::argument_type
was deprecated in C++17. What is the reason behind it? And what ISO WG21 paper was proposing that?
Yes: std::bind should be replaced by lambda For almost all cases, std::bind should be replaced by a lambda expression. It's idiomatic, and results in better code. There is almost no reason post C++11 to use std::bind .
std::function can hold function objects (including lambdas), as well as function pointers with the correct signature. So it is more versatile.
If it is small, like 3-5 CPU instructions then yes std::function will make it slower, because std::function is not inlined into outer calling code. You should use only lambda and pass lambda as template parameter to other functions, lambdas are inlined into calling code.
The relevant papers are P0005R4 (which is the paper that was voted into the draft standard) and P0090R0 (which is referenced by P0005R4).
Quotes from P0090R0:
Q2. What's wrong with result_type, etc.?
A2. These C++98/03/TR1-era typedefs predated decltype and perfect forwarding. Previously, generic code had to request information from function objects before adapting them. Now, manually communicating that information is unnecessary. decltype supersedes result_type, because the compiler can simply report what the result of calling a function object with specific arguments will be. And perfect forwarding supersedes the argument_type family, since adaptors can simply take/store/forward arbitrary arguments.
In fact, these typedefs are worse than useless. They're counterproductive, because many callable objects lack them. Function pointers and pointers to members have always lacked them. ptr_fun(), which wrapped function pointers with these typedefs, was recently removed (see [1] again). Most importantly, lambdas have always lacked these typedefs, and they are the most important function objects of all. Generic lambdas are even more incompatible.
What this means is that if a user attempts to write generic code by using the result_type family of typedefs, their code won't be generic - it'll fail to handle lambdas, generic lambdas, function pointers, etc.
These typedefs should be removed because they've become actively harmful to modern code.
The reason those typedefs exist are so things like not1
, bind1st
and friends, could query the callables passed to them and retrieve the type of the result of invoking the callable, its argument types etc.
To make their use palatable, a lot of support machinery, like unary_function
, ptr_fun
, mem_fun
etc. were also defined. Notice how all of these are limited to adapting callables taking one or two arguments only, so they're rather limited in that sense.
Now that we have decltype
that can be used to deduce a callable's return type, variadic templates and perfect forwarding to forward arbitrary number of arguments to functions, etc. the pre-C++11 mechanisms are way too cumbersome to use.
Stephan T Lavavej first proposed getting rid of these in C++17 in p0090r0. Relevant excerpts from the paper:
Q1. What are you proposing?
* Removing every mention ofresult_type
,argument_type
,first_argument_type
, andsecond_argument_type
...
* Removing the negatorsnot1()
andnot2()
, which were powered by these typedefs.
Q2. What's wrong withresult_type
, etc.?
A2. These C++98/03/TR1-era typedefs predateddecltype
and perfect forwarding. Previously, generic code had to request information from function objects before adapting them. Now, manually communicating that information is unnecessary.decltype
supersedesresult_type
, because the compiler can simply report what the result of calling a function object with specific arguments will be. And perfect forwarding supersedes theargument_type
family, since adaptors can simply take/store/forward arbitrary arguments.
If you search the paper for [func.wrap.func]
, it talks specifically about removing the std::function
typedefs you're asking about.
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