Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
指向具有不同参数的成员函数的指针的容器 我到处寻找(现代C++设计和合作),但我找不到一个好方法来存储一组接受不同参数的回调并在不同的类上操作。我之所以需要它,是因为我希望我的应用程序的每个对象都有可能将其方法之一的执行延迟到主时钟对象,该对象跟踪当前时间,可以在正确的时刻调用此方法。我的目标代码大致如下:_C++_Templates_Callback_Scheduling_Generic Programming - Fatal编程技术网

指向具有不同参数的成员函数的指针的容器 我到处寻找(现代C++设计和合作),但我找不到一个好方法来存储一组接受不同参数的回调并在不同的类上操作。我之所以需要它,是因为我希望我的应用程序的每个对象都有可能将其方法之一的执行延迟到主时钟对象,该对象跟踪当前时间,可以在正确的时刻调用此方法。我的目标代码大致如下:

指向具有不同参数的成员函数的指针的容器 我到处寻找(现代C++设计和合作),但我找不到一个好方法来存储一组接受不同参数的回调并在不同的类上操作。我之所以需要它,是因为我希望我的应用程序的每个对象都有可能将其方法之一的执行延迟到主时钟对象,该对象跟踪当前时间,可以在正确的时刻调用此方法。我的目标代码大致如下:,c++,templates,callback,scheduling,generic-programming,C++,Templates,Callback,Scheduling,Generic Programming,在class1的void executeAction1defered(int-time,int-arg1,bool-arg2)方法中,如果time是将来需要的执行时间,则应该有如下内容: Clock::defer(time, Class1::action1, this, arg1, arg2); 在Clock::defer(?什么签名??)中,表示此任务的对象存储在优先级队列中,其中时间是关键。对于每个时钟量程,任务列表将被遍历,需要在此量程中运行的任务将被执行。请注意,我使用了“defer”

class1
void executeAction1defered(int-time,int-arg1,bool-arg2)
方法中,如果time是将来需要的执行时间,则应该有如下内容:

Clock::defer(time, Class1::action1, this, arg1, arg2);
Clock::defer(?什么签名??)
中,表示此任务的对象存储在优先级队列中,其中时间是关键。对于每个
时钟
量程,任务列表将被遍历,需要在此量程中运行的任务将被执行。请注意,我使用了“defer”作为静态函数,因为我打算使用singleton的
Clock
对象,但它也可以是成员函数,这只是选择的问题

我曾经考虑过使用
void*
来保留一个数量可变的参数,但让我的
action1()
方法接受
void*
是非常糟糕的,这也是因为每次直接使用此函数时,我都需要为参数创建一个结构,而不会延迟它

我在过去曾多次遇到过这种问题,但我从未找到真正体面的解决办法。请注意,由于这是一个小型的多平台项目,对于没有经验的程序员来说,简单的构建非常重要,可以扩展它,所以我不想使用boost。但是,我们所讨论的平台的每个编译器都有
std::tr1
bind。问题是:如何定义泛型函数的容器,每个泛型函数接受可变数量的参数(最多N~5个),并且是不是从公共虚拟类派生的对象的不同成员方法?谢谢

使用
std::function
存储调用,然后使用可变模板参数转发和绑定函数参数:

class Clock
{
    vector<function<void()>> tasks;

    template<class F, class... Args>
    void defer(F f, Args&&... args)
    {
        tasks.push_back(bind(f, forward<Args>(args)...);
    }

}

void f(A a, B b);

int main()
{
    A a;
    B b;

    Clock c;
    c.push_back(f, a, b);
}
类时钟
{
向量任务;
模板
无效延迟(F,参数&…参数)
{
任务。向后推(绑定(f,向前推(args)…);
}
}
无效f(A,B);
int main()
{
A A;
B B;
时钟c;
c、 向后推(f、a、b);
}

另请参见C++11中的
std::bind
std::mem\u-fun
,存储
std::function
。您可以使用
std::bind
从不同的签名之一创建函数,例如:

std::vector<std::function<void()>> deferred;
deferred.push_back(std::bind(&Class1::action1, this, arg1, arg2));

// later...
for (auto f : deferred) f();
std::向量延迟;
推回(std::bind(&Class1::action1,this,arg1,arg2));
//后来。。。
对于(自动f:延迟)f();
如果C++11不是一个选项,那么Boost有非常相似的
函数
绑定
模板。我认为它们可能也存在于TR1中,尽管我没有任何历史参考来检查

如果Boost真的不是一个选项(而且TR1没有提供这些),那么我强烈建议您将其作为一个选项;否则,请以Boost为例说明如何实现它。如果没有可变模板,它会变得非常复杂


(并且,因为你提到了现代C++设计,阅读了关于类型列表的部分;这是你如何在没有可变模板的情况下完成的)。

因为回调被延迟,包括它们提供的参数,所以真正的签名将是<代码>空洞()。,即时钟对象本身不提供参数,也不需要计算结果。因此,通常需要将成员函数指针(或其他函数指针)与所需参数绑定在一起,并传递结果(函数对象)这是
boost::bind
/
std::tr1::bind
boost::function
/
std::function
进入的位置-或C++11 lambdas:

Clock::defer(time, boost::bind(&Class1::action1, this, arg1, arg2));
//C++11 lambda:
Clock::defer(time, [=](){action1(arg1, arg2);} );
但是你正在做的已经完成了-看看Boost.Asio timers:

boost::asio::basic_deadline_timer timer(ioService, expiryTime);
timer.async_wait([=](){action1(arg1, arg2);} //perform action1 when the timer is done

为什么要存储具有不同参数集的函数?如何调用这些函数?我理解您的问题,您可以只绑定除一个参数(时间)之外的所有参数-然后您将存储所有具有相同签名(时间)的函数,但内部可能会用不同的签名包装函数。您可以使用a作为签名,并让每个方法处理参数。@aleguna不,对不起…tr1 only不应该是
std::forward(args…
?另外,它的性能如何?是否可以与直接调用函数相比(假设所有
args…
都支持移动语义)?我认为我的用法是正确的,椭圆将覆盖forward的模板参数。性能与使用虚拟接口
类函数{virtual void f()=0;}相同
然后手动为每个绑定函数创建子类,并使用成员变量来存储参数。也就是说,它将获取参数的副本,然后调用多态函数。这种方法允许我也使用成员函数吗?看起来很棒。btwYes
std::bind
将获取一个成员函数,然后是第一个参数Meter是这个指针的指针。所以
类A{void f(B);}
绑定(&A::f,this,B)
一样绑定。另请参见
std::mem\u fun
(您可以像
c.defer(&A::f,this,…)
@Alexardarsonik:我认为所有这些平台都支持
函数
绑定
。您可能需要手动扩展可变模板参数功能(即使用0,1,2…n-1以及每个可能数量的模板参数进行n次不同调用),因为这项功能在ios或osx上可能还不可用。我认为它在win和android上可用。所以看起来我可以做到