受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;
}在没有模板lambda的c++11/c++14/c++17,中,可以使用具有模板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捕获负责捕获所需的变量。
除了简单性之外,上面列出的两种方法之间还有其他具体的区别吗?效率如何?
发布于 2019-07-03 19:33:54
我在第二个例子中看到的主要缺点是,为了模拟lambda捕获,需要显式地将所有局部变量(在本例中为int )传递给函数器。
我不同意。
您可以看到lambda几乎是一个类/结构,其中包含一个operator()和一些对应于捕获的变量的成员。
因此,不是
[&]<int I>(auto& x) { std::get<I>(x) += I + a; };你可以写(已经从C++11)
struct nal // not a lambda
{
int const & a;
template <int I, typename T>
auto operator() (T & x) const
{ std::get<I>(x) += I + a; }
};并按如下方式使用它
call<0>(nal{a}, t);我看到的函数式的主要缺点(我认为这是一个缺点)是,你不能简单地通过引用或值([&]或[=])来捕获所有外部变量,但是你必须显式地列出你在定义函数器和初始化函数器对象时使用的所有变量。
关闭主题:注意到我已经在我的nal结构中标记了const operator()。
如果您不修改捕获的变量,那么lambda等价于具有常量operator()的函数器。
如果将函数器作为常量引用传递,这一点很重要
template <int I, class Lambda, class... ArgsType>
void call (Lambda const & F, ArgsType&& ...args)
{ // ......^^^^^^^^^^^^^^ now F is a constant reference
F.template operator()<I>(std::forward<ArgsType>(args)...); // compilation error
// if operator()
// isn't const
} 如果operator()不是const,则会出现编译错误
https://stackoverflow.com/questions/56865775
复制相似问题