为啥 std::apply 可以调用 lambda 而不是等效的模板函数?

Posted

技术标签:

【中文标题】为啥 std::apply 可以调用 lambda 而不是等效的模板函数?【英文标题】:Why can std::apply call a lambda but not the equivalent template function?为什么 std::apply 可以调用 lambda 而不是等效的模板函数? 【发布时间】:2017-08-07 03:52:26 【问题描述】:

以下代码 sn-p(在 OS X 上使用 gcc 6.3.0 和 -std=c++17 编译)演示了我的难题:

#include <experimental/tuple>

template <class... Ts>
auto p(Ts... args) 
  return (... * args);


int main() 
  auto q = [](auto... args) 
    return (... * args);
  ;

  p(1,2,3,4); // == 24
  q(1,2,3,4); // == 24

  auto tup = std::make_tuple(1,2,3,4);
  std::experimental::apply(q, tup); // == 24
  std::experimental::apply(p, tup); // error: no matching function for call to 'apply(<unresolved overloaded function type>, std::tuple<int, int, int, int>&)'

为什么apply可以成功推断出对lambda的调用,但不能推断出对模板函数的调用?这是预期的行为吗?如果是,为什么?

【问题讨论】:

Pass a function template to other function 可能重复? 这个问题是指将模板函数传递给另一个函数——这个问题是指在通用 lambda(有效)与模板函数(无效)上使用 apply。 "那个问题是指将一个模板函数传递给另一个函数" 就像将p(一个函数模板)传递给apply(另一个函数(模板))一样。 .? 这个问题的答案并没有解释为什么函子类确实有效,也没有提到通用 labmda 与函子类是一样的事实,但除此之外,就是这样 【参考方案1】:

两者之间的区别在于p 是一个函数模板,而q - 一个通用的lambda - 几乎是一个带有模板化调用运算符 的闭包类。

虽然上述调用运算符的定义与p 的定义非常相似,但闭包类根本不是模板,因此它不会停留在std::experimental::apply 的模板参数解析方式中。

这可以通过将p 定义为仿函数类来检查:

struct p

   auto operator()(auto... args)
    return (... * args); 
;

【讨论】:

是的,效果很好。感谢您清楚地阐明了通用 lambda 和模板函数之间的区别——这将在未来成为一个有用的工具。

以上是关于为啥 std::apply 可以调用 lambda 而不是等效的模板函数?的主要内容,如果未能解决你的问题,请参考以下文章

为啥lambda中的变量无法调用函数[关闭]

为啥 lambda 的调用运算符隐式为 const?

为啥使用 lambda 函数?

为啥这个涉及 list.index() 调用的 lambda 这么慢?

Python:不明白为啥在 GUI“command=”中需要 lambda 来调用函数 [重复]

为啥要缓存对 MySQL RDS 的 AWS Lambda python 调用?