C++需要一个容器来存储用户定义的函数
C++ need a container to store user defined function
我正在尝试在用户定义的函数和数据之间创建一个接口。假设我需要创建一个名为 MapFun()
的函数,MapFun()
的输入包括用户定义函数 (UDF) 句柄和 UDF 输入。
void userFun1(Data data, int in1, int in2){
// user defined function 1;
}
void userFun2(Data data, int in1, int in2, std::string s){
// user defined function 2;
}
// ...
// apply user function 1 on data
MapFun(@userFun1, data, 3, 4);
// apply user function 2 on data
MapFun(@userFun2, data, 1, 2, "algorithm");
用户将编写 userFun
并用 MapFun()
应用它。那么,如何设计MapFun()
呢?用户函数可能有不同的输入,签名无法预测。此外,MapFun()
不会立即评估 userFun
,而是存储所有 userFun
并进行惰性评估。
非常感谢任何建议。
如果您只需要从 C++17 向后移植 std::invoke
,那么,它的最简单形式非常简单forward
:
template<class F, class... Args> decltype(auto) invoke(F &&f, Args &&...args) {
return ::std::forward<F>(f)(::std::forward<Args>(args)...);
}
如果我没理解错的话,你只是想存储一个函数和一组参数,以便以后调用它们。这正是 std::bind
所做的(无论如何,它所做的最简单的事情)。事实上,您可以直接使用 std::bind
代替 MapFun
:
auto func1 = std::bind(userFun1, data, 3, 4);
auto func2 = std::bind(userFun2, data, 1, 2, "algorithm");
// ... and later,
func1();
func2();
请注意其中的 auto
:您不能(可移植地)编写由 std::bind
编辑的任何对象的类型 return,并且这两个示例对象将具有不同的类型.但是这两者都会隐式转换为通用类型 std::function<void()>
。您可以将一堆 std::function<void()>
对象存储在几乎任何您想要的容器类型中,以备后用:
std::map<unsigned int, std::function<void()>> func_map;
func_map[0] = std::bind(userFun1, data, 3, 4);
func_map[1] = std::bind(userFun2, data, 1, 2, "algorithm");
// ...
auto func_iter = func_map.find(key);
if (func_iter != func_map.end() && func_iter->second) {
(func_iter->second)();
}
当然,如果你想使用你的函数名,and/or如果你需要明确的通用return类型与其他模板或其他东西一起工作,你可以只包装std::bind
:
template <class F, class... Args>
std::function<void()> MapFun(F&& f, Args&&... args) {
return std::bind<void>(std::forward<F>(f), std::forward<Args>(args)...);
}
或者如果您的 MapFun
应该将可调用对象存储在某些 class 成员容器或其他东西中,而不仅仅是创建和 return 一个(不清楚),它可以当然可以通过使用 std::bind
然后将结果添加到您需要的任何容器中来做到这一点。
User function may have different inputs and the signature can't be predicted.
这似乎是可变参数模板的典型作品
In addition, MapFun()
won't evaluate userFun
immediately, instead, it stores all userFun
and do a lazy evaluation.
不确定是否理解,但我想您可以使用 std::bind()
或使用 lambda 函数获得您想要的东西。
我提出以下 C++14 可变参数模板 MapFun()
函数,return 一个捕获用户函数和参数的 lambda 函数。该功能可以稍后执行。
template <typename F, typename ... Args>
auto MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
以下是完整的工作示例
#include <iostream>
template <typename F, typename ... Args>
auto MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
void userFun2 (int i1, int i2, std::string const & s)
{ std::cout << "uf2, " << i1 << ", " << i2 << ", " << s << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
auto l2 = MapFun(userFun2, 3, 4, "five");
l2();
l1();
}
我正在尝试在用户定义的函数和数据之间创建一个接口。假设我需要创建一个名为 MapFun()
的函数,MapFun()
的输入包括用户定义函数 (UDF) 句柄和 UDF 输入。
void userFun1(Data data, int in1, int in2){
// user defined function 1;
}
void userFun2(Data data, int in1, int in2, std::string s){
// user defined function 2;
}
// ...
// apply user function 1 on data
MapFun(@userFun1, data, 3, 4);
// apply user function 2 on data
MapFun(@userFun2, data, 1, 2, "algorithm");
用户将编写 userFun
并用 MapFun()
应用它。那么,如何设计MapFun()
呢?用户函数可能有不同的输入,签名无法预测。此外,MapFun()
不会立即评估 userFun
,而是存储所有 userFun
并进行惰性评估。
非常感谢任何建议。
如果您只需要从 C++17 向后移植 std::invoke
,那么,它的最简单形式非常简单forward
:
template<class F, class... Args> decltype(auto) invoke(F &&f, Args &&...args) {
return ::std::forward<F>(f)(::std::forward<Args>(args)...);
}
如果我没理解错的话,你只是想存储一个函数和一组参数,以便以后调用它们。这正是 std::bind
所做的(无论如何,它所做的最简单的事情)。事实上,您可以直接使用 std::bind
代替 MapFun
:
auto func1 = std::bind(userFun1, data, 3, 4);
auto func2 = std::bind(userFun2, data, 1, 2, "algorithm");
// ... and later,
func1();
func2();
请注意其中的 auto
:您不能(可移植地)编写由 std::bind
编辑的任何对象的类型 return,并且这两个示例对象将具有不同的类型.但是这两者都会隐式转换为通用类型 std::function<void()>
。您可以将一堆 std::function<void()>
对象存储在几乎任何您想要的容器类型中,以备后用:
std::map<unsigned int, std::function<void()>> func_map;
func_map[0] = std::bind(userFun1, data, 3, 4);
func_map[1] = std::bind(userFun2, data, 1, 2, "algorithm");
// ...
auto func_iter = func_map.find(key);
if (func_iter != func_map.end() && func_iter->second) {
(func_iter->second)();
}
当然,如果你想使用你的函数名,and/or如果你需要明确的通用return类型与其他模板或其他东西一起工作,你可以只包装std::bind
:
template <class F, class... Args>
std::function<void()> MapFun(F&& f, Args&&... args) {
return std::bind<void>(std::forward<F>(f), std::forward<Args>(args)...);
}
或者如果您的 MapFun
应该将可调用对象存储在某些 class 成员容器或其他东西中,而不仅仅是创建和 return 一个(不清楚),它可以当然可以通过使用 std::bind
然后将结果添加到您需要的任何容器中来做到这一点。
User function may have different inputs and the signature can't be predicted.
这似乎是可变参数模板的典型作品
In addition,
MapFun()
won't evaluateuserFun
immediately, instead, it stores alluserFun
and do a lazy evaluation.
不确定是否理解,但我想您可以使用 std::bind()
或使用 lambda 函数获得您想要的东西。
我提出以下 C++14 可变参数模板 MapFun()
函数,return 一个捕获用户函数和参数的 lambda 函数。该功能可以稍后执行。
template <typename F, typename ... Args>
auto MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
以下是完整的工作示例
#include <iostream>
template <typename F, typename ... Args>
auto MapFun (F const & f, Args const & ... args)
{ return [=]{ f(args...); }; }
void userFun1 (int i1, int i2)
{ std::cout << "uf1, " << i1 << ", " << i2 << std::endl; }
void userFun2 (int i1, int i2, std::string const & s)
{ std::cout << "uf2, " << i1 << ", " << i2 << ", " << s << std::endl; }
int main ()
{
auto l1 = MapFun(userFun1, 1, 2);
auto l2 = MapFun(userFun2, 3, 4, "five");
l2();
l1();
}