繁体   English   中英

指向具有不同参数的成员函数的指针的容器

[英]Container for pointers to member functions with different arguments

我到处都在寻找(现代C ++设计和合作),但是我找不到一种好方法来存储一组接受不同参数并在不同类上运行的回调。 我之所以需要这样做,是因为我希望应用程序的每个对象都可以将其方法之一的执行推迟到主Clock对象上,该主Clock对象可以跟踪当前时间,可以在适当的时候调用此方法。 我所针对的代码大致如下:

class1void executeAction1Deferred(int time, int arg1, bool arg2)方法中,其中time是将来所需的执行时间,应该是这样的:

Clock::defer(time, Class1::action1, this, arg1, arg2);

Clock::defer(??? what signature ????) ,代表此Task的对象存储在优先级队列中,其中时间是键。 然后,将遍历每个“ Clock ”任务列表,然后执行需要在该任务中运行的任务。 请注意,我已经将“ defer”用作静态函数,因为我打算使用Singleton的Clock对象,但是它也可以是成员函数,这只是选择的问题。

我曾考虑过使用void*来保留可变数量的参数,但是让我的action1()方法接受void*确实很糟糕,这还因为每次我直接使用此函数时都需要为参数构造一个结构而不会推迟。

过去,我多次遇到过这个问题,但从未找到真正合适的解决方案。 请注意,由于这是一个小型的多平台项目,因此对于缺乏经验的程序员来说,构建简单的可以扩展的项目至关重要,我不想使用boost。 但是,我们处理的平台的每个编译器都有std::tr1绑定。 问题是:如何定义一个泛型函数的容器,每个泛型函数接受可变数量的参数(最多N〜5个),并且是不是从公共虚类派生的对象的不同成员方法? 谢谢

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

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);
}

另请参见std::bindstd::mem_fun

在C ++ 11中,存储std::function<void()> 您可以使用std::bind从其他签名之一创建函数,例如:

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

// later...
for (auto f : deferred) f();

如果没有C ++ 11,则Boost具有非常相似的functionbind模板。 我认为它们可能也存在于TR1中,尽管我没有任何历史参考可查。

如果Boost确实不是一个选项(而TR1不提供这些选项),那么我强烈建议您将其设为一个选项; 否则,请使用Boost作为实现此方法的示例。 没有可变参数的模板,它将变得非常毛茸茸。

(并且由于您提到了Modern C ++ Design,因此请阅读类型列表中的部分;这就是不使用可变参数模板的方式)。

由于您的回调将包括其提供的参数而被推迟,因此实际的签名将为void() ,即Clock对象将不会自行提供参数,也无需评估结果。 因此,通常您会希望将成员函数指针(或其他函数指针)与所需的参数绑定在一起,并将结果(函数对象)传递给时钟。 这是boost::bind / std::tr1::bindboost::function / std::function<void()>出现的地方-或C ++ 11 lambdas:

Clock::defer(time, boost::bind(&Class1::action1, this, arg1, arg2));
//C++11 lambda:
Clock::defer(time, [=](){action1(arg1, arg2);} );

但是您正在做的事情已经完成-看一下Boost.Asio计时器:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM