C++ 如何在标准库中使用std::bind并保存返回类型?

C++ 如何在标准库中使用std::bind并保存返回类型?,c++,c++11,stl,bind,C++,C++11,Stl,Bind,我正在处理一个类,该类通过将函数绑定到如下队列中来调度函数: std::queue <void()> q; template<typename R,typename... ArgsT> void schedule(R& fn, ArgsT&... args) { q.push(std::bind(fn, std::forward<ArgsT>(args)...) );

我正在处理一个类,该类通过将函数绑定到如下队列中来调度函数:

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)...) );
        };
std::队列q;
模板
无效的
明细表(R&fn、ArgsT和…args)
{
q、 推送(std::bind(fn,std::forward(args)…);
};
模板
无效的
明细表(R&&fn、ArgsT&&fn、args)
{
q、 推送(std::bind(fn,std::forward(args)…);
};
正如您所见,我在
队列中创建了类型
void()
,以使其包含任何类型的函数对象,但现在在执行它时无法获得返回。我该怎么解决这个问题

注意:我不想使用像boost这样的外部库,也不知道用户会传递什么样的函数

注意:我不想使用像boost这样的外部库,我也不想 知道用户将传递什么样的函数

在这种情况下,我通常在队列中使用基类(来自命令模式),然后有两个实现,一个封装绑定,另一个(也封装绑定)公开一个允许获取返回值的函数

下面是一个返回专门化的示例(最后):

#包括
#包括
#包括
结构ACmd
{
虚拟void exec()=0;
虚拟~ACmd(){}
};
模板
结构Cmd;
模板
结构Cmd:ACmd
{
R结果;
std::函数func;
模板
Cmd(F&&func,Args&&…Args):结果(),func()
{
自动f=std::bind(std::forward(func)、std::forward(args)…);
func_uz=[f](){
返回f();
};
}
虚拟void exec(){
结果=函数();
}
常量R&getResult()常量{返回结果}
};
//为方便起见,可通过值或ptr返回函数-
//-你的选择
模板
Cmd*Cmd(F&&func,Args&&Args)
{
返回新Cmd(func,std::forward(args)…);
}
//... 为虚空而超载。。。
int foo(int arg){
返回arg;
}
int main(){
自动x=cmd(foo,10);
x->exec();

std::cout getResult()执行
队列
中每个元素的结果,它是
void
,您已经这样定义了它。如果传入的函数需要返回值,则需要限制类型返回到固定类型时,请使用实用程序,如
std::any
std::variant
或一些协变类型(可以使用
std::unique_ptr
std::shared_ptr

最简单的方法是修复返回类型(在编译时)


如果您不知道返回值的类型,您希望如何处理返回值?C++17中有
std::any
,或者
boost::any
。但是您似乎不想使用它们中的任何一个。@Kevin这是类调度队列中的函数并同时执行它们的一部分,用户可以在函数执行后获得返回值ecution完成了,所以我想知道如何保存它,以便通过std::future获取它并将其返回到user@Rakete1111我会看看std::any,但是有没有更好的解决方案?返回一个合适类型的未来。
#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;
}
template <typename R>
using MQ = std::queue<std::function<R()>>;

MQ<int> q;
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;
}