如何在标准库中使用std::bind并保存return类型?
How to use std::bind with the standard library and save the return type?
我正在研究 class 通过将函数绑定到队列中来安排函数的方法:
std::queue <void()> q;
template<typename R,typename... ArgsT>
void
schedule(R& fn, ArgsT&... args)
{
q.push(std::bind(fn, std::forward<ArgsT>(args)...) );
};
template<typename R,typename... ArgsT>
void
schedule(R&& fn, ArgsT&&... args)
{
q.push(std::bind(fn, std::forward<ArgsT>(args)...) );
};
如您所见,我在 queue
void()
中创建了类型以使其包含任何类型的函数对象,但现在我在执行它时无法获得 return .我应该怎么做才能解决这个问题?
注意:我不想使用boost这样的外部库,也不知道用户会传递什么样的函数。
Note: I don't want to use an external library like boost and I don't
know what's the kind of function the user will pass it.
在这种情况下,我通常做的是在我的队列中使用基本 class(来自命令模式),然后有两个实现,一个包装绑定,另一个(也包装bind) 公开一个允许获取 return 值的函数。
这是 returning 专业化的示例(最后):
#include <iostream>
#include <functional>
#include <memory>
struct ACmd
{
virtual void exec() = 0;
virtual ~ACmd(){}
};
template <class F>
struct Cmd;
template <class R, class ... Args>
struct Cmd<R(Args...)> : ACmd
{
R result_;
std::function<R()> func_;
template <class F>
Cmd(F&& func, Args&&... args): result_(), func_()
{
auto f = std::bind(std::forward<F>(func), std::forward<Args>(args)...);
func_ = [f](){
return f();
};
}
virtual void exec(){
result_ = func_();
}
const R& getResult() const {return result_;}
};
// Make function for convenience, could return by value or ptr -
// - your choice
template <class R, class F, class ...Args>
Cmd<R(Args...)>* cmd(F&& func, Args&&... args)
{
return new Cmd<R(Args...)>(func, std::forward<Args>(args)...);
}
//... And overload for void...
int foo(int arg) {
return arg;
}
int main() {
auto x = cmd<int>(foo, 10);
x->exec();
std::cout << x->getResult() << std::endl;
return 0;
}
queue
中每个元素的执行结果是void
,你已经这样定义了。如果传入的函数需要 return 一个值,那么您需要将 returned 的类型限制为固定类型,使用 std::any
、std::variant
或某些协变类型(可能带有 std::unique_ptr
或 std::shared_ptr
)。
最简单的是固定return类型(在编译时);
template <typename R>
using MQ = std::queue<std::function<R()>>;
MQ<int> q;
请参阅下面的示例。
队列声明需要是queue
个对象,例如std::function
个对象。 bind
中的 return 值可以分配给 function
,然后按预期使用。
std::function
是一个多态函数包装器,它实现了类似于 any
的类型擦除模式,但专为函数和其他可调用对象而设计。
通过 example;
template <typename R>
using MQ = std::queue<std::function<R()>>;
MQ<int> q;
template<typename R,typename... ArgsT>
void
schedule(R&& fn, ArgsT&&... args)
{
q.push(std::bind(std::forward<R>(fn), std::forward<ArgsT>(args)...) );
};
int main()
{
schedule([](int a) { std::cout << "function called" << std::endl; return a; }, 42);
std::cout << q.front()() << std::endl;
}
我正在研究 class 通过将函数绑定到队列中来安排函数的方法:
std::queue <void()> q;
template<typename R,typename... ArgsT>
void
schedule(R& fn, ArgsT&... args)
{
q.push(std::bind(fn, std::forward<ArgsT>(args)...) );
};
template<typename R,typename... ArgsT>
void
schedule(R&& fn, ArgsT&&... args)
{
q.push(std::bind(fn, std::forward<ArgsT>(args)...) );
};
如您所见,我在 queue
void()
中创建了类型以使其包含任何类型的函数对象,但现在我在执行它时无法获得 return .我应该怎么做才能解决这个问题?
注意:我不想使用boost这样的外部库,也不知道用户会传递什么样的函数。
Note: I don't want to use an external library like boost and I don't know what's the kind of function the user will pass it.
在这种情况下,我通常做的是在我的队列中使用基本 class(来自命令模式),然后有两个实现,一个包装绑定,另一个(也包装bind) 公开一个允许获取 return 值的函数。
这是 returning 专业化的示例(最后):
#include <iostream>
#include <functional>
#include <memory>
struct ACmd
{
virtual void exec() = 0;
virtual ~ACmd(){}
};
template <class F>
struct Cmd;
template <class R, class ... Args>
struct Cmd<R(Args...)> : ACmd
{
R result_;
std::function<R()> func_;
template <class F>
Cmd(F&& func, Args&&... args): result_(), func_()
{
auto f = std::bind(std::forward<F>(func), std::forward<Args>(args)...);
func_ = [f](){
return f();
};
}
virtual void exec(){
result_ = func_();
}
const R& getResult() const {return result_;}
};
// Make function for convenience, could return by value or ptr -
// - your choice
template <class R, class F, class ...Args>
Cmd<R(Args...)>* cmd(F&& func, Args&&... args)
{
return new Cmd<R(Args...)>(func, std::forward<Args>(args)...);
}
//... And overload for void...
int foo(int arg) {
return arg;
}
int main() {
auto x = cmd<int>(foo, 10);
x->exec();
std::cout << x->getResult() << std::endl;
return 0;
}
queue
中每个元素的执行结果是void
,你已经这样定义了。如果传入的函数需要 return 一个值,那么您需要将 returned 的类型限制为固定类型,使用 std::any
、std::variant
或某些协变类型(可能带有 std::unique_ptr
或 std::shared_ptr
)。
最简单的是固定return类型(在编译时);
template <typename R>
using MQ = std::queue<std::function<R()>>;
MQ<int> q;
请参阅下面的示例。
队列声明需要是queue
个对象,例如std::function
个对象。 bind
中的 return 值可以分配给 function
,然后按预期使用。
std::function
是一个多态函数包装器,它实现了类似于 any
的类型擦除模式,但专为函数和其他可调用对象而设计。
通过 example;
template <typename R>
using MQ = std::queue<std::function<R()>>;
MQ<int> q;
template<typename R,typename... ArgsT>
void
schedule(R&& fn, ArgsT&&... args)
{
q.push(std::bind(std::forward<R>(fn), std::forward<ArgsT>(args)...) );
};
int main()
{
schedule([](int a) { std::cout << "function called" << std::endl; return a; }, 42);
std::cout << q.front()() << std::endl;
}