为什么 std::function::argument_type 已被弃用?

Why std::function::argument_type has been deprecated?

我在 cppreference 上看到 std::function::argument_type 在 C++17 中被弃用。其背后的原因是什么? ISO WG21 的哪篇论文提出了这个建议?

相关论文P0005R4 (which is the paper that was voted into the draft standard) and P0090R0(P0005R4引用)

引自 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.

这些 typedef 存在的原因是像 not1, bind1st 和朋友这样的东西,可以查询传递给他们的可调用对象并检索调用可调用对象的结果类型、它的参数类型等。

为了使它们的使用更容易接受,还定义了许多支持机制,如 unary_function, ptr_fun, mem_fun 等。请注意,所有这些都仅限于调整仅采用一个或两个参数的可调用对象,因此在这个意义上它们相当有限。

现在我们有 decltype 可用于推断可调用对象的 return 类型、可变参数模板和完美转发以将任意数量的参数转发给函数等。pre-C+ +11 机制使用起来太麻烦了。

Stephan T Lavavej 在 p0090r0 中首次提出在 C++17 中去除这些。相关论文摘录:

Q1. What are you proposing?
* Removing every mention of result_type, argument_type, first_argument_type, and second_argument_type ...
* Removing the negators not1() and not2(), which were powered by these typedefs.

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.

如果您在论文中搜索 [func.wrap.func],它会专门讨论如何删除您询问的 std::function typedef。