【发布时间】:2019-11-13 21:17:40
【问题描述】:
受this question 的启发,我想将c++20 模板lambda 的使用与具有模板operator() 的函子进行比较。
作为一个测试用例,考虑一个模板函数call,它接受一个模板 lambda 作为参数,并调用这个 lambda 并使用一些模板参数对其进行实例化。下面的c++20 代码就是这个想法的例证。
#include <tuple>
#include <utility>
template <int I, class Lambda, class... ArgsType>
void call(Lambda&& F, ArgsType&& ...args)
{
F.template operator()<I>(std::forward<ArgsType>(args)...);
}
int main() {
std::tuple<int, double, int> t{0,0,0};
int a = 2;
auto f = [&]<int I>(auto& x) { std::get<I>(x) += I + a; };
call<0>(f, t);
return 0;
}
在c++11/c++14/c++17 中,没有模板 lambda,可以使用具有模板 operator() 的函子来实现相同的任务,如下面的代码所示。
#include <tuple>
#include <utility>
template <int I, class Lambda, class... ArgsType>
void call(Lambda&& F, ArgsType&& ...args)
{
F.template operator()<I>(std::forward<ArgsType>(args)...);
}
struct Functor {
template <int I, class T>
void operator()(const int& a, T& x) { std::get<I>(x) += I + a; };
};
int main() {
std::tuple<int, double, int> t{0,0,0};
int a = 2;
Functor func{};
call<0>(func, a, t);
}
我在第二个示例中看到的主要缺点是,为了模拟 lambda 捕获,需要将所有局部变量(在本例中为 int a)显式传递给函子。如果Functor::operator() 需要来自其“所有者”的许多变量,这可能会很乏味。最终,也可以将指针this 传递给Functor::operator()。
c++20 示例中不存在此类复杂情况,其中 lambda 捕获负责捕获所需的变量。
除了简单之外,上述两种方法之间还有其他具体区别吗?效率怎么样?
【问题讨论】:
-
这与普通函子和泛型 lambda 或(完全可推导的)模板化函子和泛型 lambda 之间的比较基本相同。
-
@Quentin 比较可能类似,但是例如,您不能使用成员模板定义本地类,因此您需要像第二个代码中那样在 main 之外声明函子,而 c第一个代码的 ++20 lambda 是本地的。
-
似乎您回答了自己的问题。顺便说一句,这没有错,但最好将答案放在答案中,而不是问题和 cmets...
-
C++14 已经有了通用 lambda,可以使用显式模板参数调用(使用丑陋的
operator()<>语法)。 C++20 仅允许为它们提供显式模板 参数 列表(这对概念特别有用)。 -
@DavisHerring 但如何使用非类型模板参数?
标签: c++ templates lambda variadic-templates c++20