首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >template lambda vs functor with template operator()

template lambda vs functor with template operator()
EN

Stack Overflow用户
提问于 2019-07-03 16:18:15
回答 1查看 236关注 0票数 0

this question的启发,我想将c++20模板lambda的使用与具有模板operator()的函数器进行比较。

作为一个测试用例,考虑一个模板函数call,它接受一个模板lambda作为参数,并调用这个lambda,用一些模板参数实例化它。下面的c++20代码举例说明了这一思想。

代码语言:javascript
复制
#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()的函数器来实现相同的任务,如以下代码所示。

代码语言:javascript
复制
#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捕获负责捕获所需的变量。

除了简单性之外,上面列出的两种方法之间还有其他具体的区别吗?效率如何?

EN

回答 1

Stack Overflow用户

发布于 2019-07-03 19:33:54

我在第二个例子中看到的主要缺点是,为了模拟lambda捕获,需要显式地将所有局部变量(在本例中为int )传递给函数器。

我不同意。

您可以看到lambda几乎是一个类/结构,其中包含一个operator()和一些对应于捕获的变量的成员。

因此,不是

代码语言:javascript
复制
[&]<int I>(auto& x) { std::get<I>(x) += I + a; };

你可以写(已经从C++11)

代码语言:javascript
复制
struct nal // not a lambda
 {
   int const & a;

   template <int I, typename T>
   auto operator() (T & x) const
    { std::get<I>(x) += I + a; }
 };

并按如下方式使用它

代码语言:javascript
复制
call<0>(nal{a}, t);

我看到的函数式的主要缺点(我认为这是一个缺点)是,你不能简单地通过引用或值([&][=])来捕获所有外部变量,但是你必须显式地列出你在定义函数器和初始化函数器对象时使用的所有变量。

关闭主题:注意到我已经在我的nal结构中标记了const operator()

如果您不修改捕获的变量,那么lambda等价于具有常量operator()的函数器。

如果将函数器作为常量引用传递,这一点很重要

代码语言:javascript
复制
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,则会出现编译错误

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56865775

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档