何时使用函数模板而不是通用 lambda?
Posted
技术标签:
【中文标题】何时使用函数模板而不是通用 lambda?【英文标题】:When use a function template instead of a generic lambda? 【发布时间】:2014-05-17 13:20:39 【问题描述】:我可以写一个函数模板:
template<typename T>
void f1(T parameter) ...
但在 C++14 中,我也可以创建一个通用 lambda:
auto f2 = [](auto parameter) ... ;
f1
内可以直接参考T
。在f2
中,没有T
可以引用,但我可以使用decltype
获得相同的效果:
auto f2 = [](auto parameter)
using T = decltype(param);
...
;
通用 lambda 的一个优点是我可以完美地转发它。我不能用函数模板做到这一点:
template<typename T>
void fwdToG(T&& param) g(std::forward<T>(param));
fwdToG(f1); // error!
fwdToG(f2); // okay
在某些情况下使用函数模板会比使用通用 lambda 更好吗?
【问题讨论】:
等等,你不能?为什么一个是通用参考而另一个不是?错误是什么?这会给您带来什么问题?什么是g
?
g
是我想调用的其他函数; fwdToG
是完美转发功能。错误是 f1
没有类型(它是模板,不是函数),因此尝试将其传递给 fwdToG
失败。
啊,是的,好的。那么这不是回答你的问题吗?
我展示的是通用 lambda 优于函数模板的优势。我在问函数模板是否比通用 lambda 有优势。
很公平。对于它的价值,我想不出任何东西。
【参考方案1】:
函数template
s 允许重载具有相同名称的其他函数,并通过ADL 调用它们。通用 lambda 是具有重载 ()
的对象,因此两者都不起作用。
您可以很容易地将函数重载集传递给对象:
struct foo_overload_set_t
template<class...Ts>
constexpr auto operator()(Ts&&...ts)const return foo(std::forward<Ts>(ts)...);
;
使用 RVO 可以完全优化(零开销),并且可以将整个重载集的实例传递给算法。您也可以在使用点使用 lambda 来执行此操作,它可以由宏生成。
通过更多样板,上述重载集还可以支持转换为任何调用兼容的函数指针,template
和 lambda 解决方案都不支持(lambda 要求签名匹配一个版本,不兼容)。
【讨论】:
你能举个例子说明你给函数传递一个重载集是什么意思吗? @knowitallwannabestd::sort(it1,it2,foo_overload_set_t)
将进行重载查找并在std::sort
内调用foo
。基本上,您可以将查找正确的重载包装到可以传递的对象中。
@knowitallwannabe 请注意,我没有足够强调这两个优点:重载(在class
之外,如此分布)和 ADL(在命名空间之外如此重载!)它们两个让您编写代码靠近它应该在的地方,而不是语言规定的地方。
我认为重载和 ADL 功能在您的回答中很明显,我对此表示赞同。
这是否意味着通常应该首选函数模板?或者是否存在明显的情况,泛型 Lamba 更好(作为直接函数参数除外)?以上是关于何时使用函数模板而不是通用 lambda?的主要内容,如果未能解决你的问题,请参考以下文章