为啥 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 而不是等效的模板函数?的主要内容,如果未能解决你的问题,请参考以下文章
为啥这个涉及 list.index() 调用的 lambda 这么慢?