如何制作可以接受任何类型参数的 std::functions 和 lambda

how to make std::functions and lambdas which could take any type of argument

我已经尽可能地简化了它,希望它会很清楚。 我有一个名为 Foo 的 class,它包含一个绑定到我要调用的函数的 std::function 成员。

当调用Foo::DoCallback时,执行绑定或赋值的函数。为了支持不同类型的参数,我创建了 2 个构造函数和一个不带参数的默认构造函数

一个带有 std::function 和 int 类型参数的构造函数。
Foo(std::function<void(int)> callback, int a)

一个采用 std::function 的构造函数,它采用一个 bool 参数。

Foo(std::function<void(bool)> callback, bool condition)

以及完全不带参数的默认构造函数。

Foo(std::function<void()> callback = nullptr) : Callback(callback)

总的来说,我有 3 个 lambda。 每个 lambda 接受不同类型的参数并将它们作为参数传递给将用作回调的函数。

  auto lambdaA = [](int a)
  {
    FunctionA(a);
  };

  auto lambdaB = [](bool condition)
  {
    FunctionB(condition);
  };

  auto lambdaC = []()
  {
    FunctionC();
  };

问题是,每当我需要一个具有不同类型参数的新回调时,我都必须继续创建;


有没有办法让它更简单?

这里是完整的代码

--主要--

#include <iostream>
#include <string>
#include <memory>
#include "Foo.h"
void FunctionA(int a)
{
  std::cout << "FunctionA called. param 1 = " << std::to_string(a) << "\n";
}

void FunctionB(bool condition)
{
  std::cout << "FunctionB called. param 1 = " << std::to_string(condition) << "\n";
}

void FunctionC()
{
  std::cout << "FunctionC called with no params" << "\n";
}
int main()
{
  auto lambdaA = [](int a)
  {
    FunctionA(a);
  };

  auto lambdaB = [](bool condition)
  {
    FunctionB(condition);
  };

  auto lambdaC = []()
  {
    FunctionC();
  };

  std::unique_ptr<Foo> FooPtrA = std::make_unique<Foo>(lambdaA,10);
  std::unique_ptr<Foo> FooPtrB = std::make_unique<Foo>(lambdaB ,false);
  std::unique_ptr<Foo> FooPtrC = std::make_unique<Foo>(lambdaC);

  FooPtrA->DoCallback();
  FooPtrB->DoCallback();
  FooPtrC->DoCallback();

  return 0;
}

-- Foo.h

#pragma once
#include <functional>
class Foo
{
public:
  //constructor with a parameter callback which could take an int parameter
  Foo(std::function<void(int)> callback, int a) 
  {
    Callback = std::bind(callback, a);
  }
  //constructor with a parameter callback which could take a bool parameter
  Foo(std::function<void(bool)> callback, bool condition)
  {
    Callback = std::bind(callback, condition);
  }

  //constructor with a parameter callback which takes no parameter
  Foo(std::function<void()> callback = nullptr) : Callback(callback)
  {
  }

  void DoCallback()
  {
    Callback(); //calling the callback function that is binded
  }
private:
  std::function<void()> Callback;
};

使用模板?

template<typename T>
Foo(std::function<void(T)> callback, T a) : Callback{ std::bind(callback, a); }
{}

比 Swordfish 的答案更进一步,您可以通过使用任何类型进行参数化来消除 std::function 的开销:

template<typename F, typename T>
Foo(F f, T a)
    : Callback{ std::bind(f, a) } } {}

如果您希望它适用于任意数量的参数,并正确调用移动构造函数:

template<typename F, typename... Args>
Foo(F&& f, Args&&... a)
    : Callback{ std::bind(std::forward<F>(f), std::forward<Args>(a)...) } {}