gpt4 book ai didi

c++ - 模板 lambda 与带有模板 operator() 的仿函数

转载 作者:行者123 更新时间:2023-11-28 01:19:59 24 4
gpt4 key购买 nike

灵感来自 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 捕获负责捕获所需的变量。

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

最佳答案

The main disadvantage I see in the second example is that, to emulate the lambda capture, one needs to pass explicitly all local variables (in this case int a) to the functor.

我不同意。

您几乎可以将 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,则会出现编译错误

关于c++ - 模板 lambda 与带有模板 operator() 的仿函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56865775/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com