问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/35907454/why-stdfunctionargument-type-has-been-deprecated