【问题标题】:c++ lambda pass around auto parameter typec ++ lambda传递自动参数类型
【发布时间】:2020-10-21 10:35:35
【问题描述】:

我有一个带有 auto 参数的 lambda 函数,我想将参数推送到 STL 容器中(例如 std::vector)

例如:

template <typename T>
struct A
{
    A(int a, T &&t): _a(a), _t(t){}

    int _a;
    T _t;

    void work()
    {
        _t(this);
    }
};

void test()
{
   A a(3, [](auto a_ptr)
   {
      std::cout << a_ptr->_a << std::endl;
   });

   a.work();
}

这个例子很好用。

但是,如果我想保存 a_ptr 以供以后在向量中使用,我不知道在向量模板参数中要写什么。

我认为我什至不能在 lambda 的参数类型中使用 std::function 代替 auto,因为我认为 A 的类型是递归的(T 是接受 T 的 a 的 lambda...)

无论如何,这就是我想解决的方法,但想知道是否有更好的解决方案:

struct base_a
{
    virtual void work() = 0;
};

template <typename T>
struct A : public base_a
{
    A(int a, T &&t): _a(a), _t(t){}

    int _a;
    T _t;

    virtual void work() override
    {
        _t(this);
    }
};

void test()
{
    std::vector<base_a *> v;

    A a(3, [&v](auto a_ptr)
    {
        v.push_back(a_ptr);
        std::cout << a_ptr->_a << std::endl;
    });

    a.work();

    for (auto i: v)
    {
        i->work();
    }
}

有解决这个问题的已知设计模式吗?

【问题讨论】:

  • 向量必须具有相同类型的所有项。并且 lambda 没有已知类型。如果可能,请使用 std::tuple godbolt.org/z/Gd9jhe
  • 你调用 work 多态所以你需要一个 vector 或 vector> 我会避免使用原始指针,特别是如果你拥有你的项目。
  • @doron,你是对的。在我的真实代码中,我确实使用了共享指针。这段代码只是一个简化的例子

标签: c++ lambda auto


【解决方案1】:

将 lambda 转换为不带参数的 std::function(捕获您需要的参数)。

void execute_functions(const std::vector<std::function<void()>>& functions) {
  for (const auto& item : functions) {
    item();
  }
}

int main(int argc, char** argv) {
  // declare
  std::vector<std::function<void()>> functions;

  // populate
  for (int i = 0; i < 3; ++i) {
    functions.emplace_back([i](){ // < - capture data to process here
      // do something wth data when will be called
      std::cout << i << "\n";
    });
  }

  // execute somewhere
  execute_functions(functions);
  return 0;
}

例如here

【讨论】:

  • 我无法捕获参数。 lambda 用作回调函数。我想从示例中并不清楚,但在我的实际应用程序中,lambda 被其他类/方法转发到调用类
【解决方案2】:

我可以在捕获所有参数的 lambda 中创建一个新的 lambda,然后将其放入向量中:

void test()
{
    std::vector<std::function <void ()>> v;

    A a(3, [&v](auto a_ptr)
    {
        v.push_back([a_ptr](){
            std::cout << a_ptr->_a << std::endl;
        });
    });

    a.work();

    for (auto &i: v)
    {
        i();
    }
}

但我认为从用户的角度来看(编写 test() 函数的人),继承方法更容易,因为可能有多个 lambdas 他想保留以处理不同的情况。

这会使程序流程变得不必要地复杂 IMO。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-03
    • 2016-04-16
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多