如何制作可以接受任何类型参数的 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();
};
问题是,每当我需要一个具有不同类型参数的新回调时,我都必须继续创建;
- 创建 Foo 唯一指针时需要作为参数传递的 lambda。
- 采用新类型 std::function 参数的 foo 构造函数,该参数采用其他类型的参数。
有没有办法让它更简单?
这里是完整的代码
--主要--
#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)...) } {}
我已经尽可能地简化了它,希望它会很清楚。 我有一个名为 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();
};
问题是,每当我需要一个具有不同类型参数的新回调时,我都必须继续创建;
- 创建 Foo 唯一指针时需要作为参数传递的 lambda。
- 采用新类型 std::function 参数的 foo 构造函数,该参数采用其他类型的参数。
有没有办法让它更简单?
这里是完整的代码
--主要--
#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)...) } {}